How to load an url from recyclerview newsapi - java

Im working on a news reader app that uses fragments. I get my data from the newsapi. So far I have managed to pull the data from the api and display it in a recyclerview but when I click on an item, nothing happens!
public class HomeFragment extends Fragment implements RecyclerViewAdapter.OnItemClickListener {
public static final String API_KEY= "c03ceb6a99b14050875f56xxxxxxxx";
private RecyclerView recyclerView;
private List<Article> articles = new ArrayList<>();
private RecyclerViewAdapter recyclerViewAdapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home,container,false);
recyclerView = rootView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerViewAdapter = new RecyclerViewAdapter(articles,getActivity());
recyclerViewAdapter.setOnItemClickListener(HomeFragment.this);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setNestedScrollingEnabled(false);
LoadJsonData();
return rootView;
}
public void LoadJsonData(){
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
String country = Utils.getCountry();
Call <News> call;
call = apiInterface.getNews(country,API_KEY);
call.enqueue(new Callback<News>() {
#Override
public void onResponse(Call<News> call, Response<News> response) {
if (response.isSuccessful() && response.body().getArticle() != null){
if (!articles.isEmpty()){
articles.clear();
}
articles = response.body().getArticle();
recyclerViewAdapter = new RecyclerViewAdapter(articles,getActivity());
recyclerView.setAdapter(recyclerViewAdapter);
recyclerViewAdapter.setOnItemClickListener(HomeFragment.this);
recyclerViewAdapter.notifyDataSetChanged();
} else {
Toast.makeText(getActivity(),"No result",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<News> call, Throwable t) {
}
});
}
#Override
public void onItemClick(int position) {
articles.get(position);
}
}
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<Article> articles;
private Context context;
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public RecyclerViewAdapter(List<Article> articles, Context context) {
this.articles = articles;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate((R.layout.card_view_layout), viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
final ViewHolder holder = viewHolder;
Article model = articles.get(i);
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(Utils.getRandomDrawbleColor());
requestOptions.error(Utils.getRandomDrawbleColor());
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL);
requestOptions.centerCrop();
Glide.with(context)
.load(model.getUrlToImage())
.apply(requestOptions)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
holder.progressBar.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
holder.progressBar.setVisibility(View.GONE);
return false;
}
})
.transition(DrawableTransitionOptions.withCrossFade())
.into(holder.imageView);
holder.title.setText(model.getTitle());
holder.desc.setText(model.getDescription());
holder.source.setText(model.getSource().getName());
holder.time.setText(" \u2022 " + Utils.DateToTimeFormat(model.getPublishedAt()));
}
#Override
public int getItemCount() {
return articles.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title, desc, source, time;
ImageView imageView;
ProgressBar progressBar;
public ViewHolder(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
desc = itemView.findViewById(R.id.description);
source = itemView.findViewById(R.id.source);
time = itemView.findViewById(R.id.time);
imageView = itemView.findViewById(R.id.headline_image);
progressBar = itemView.findViewById(R.id.progress_load);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (onItemClickListener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
onItemClickListener.onItemClick(position);
}
}
}
});
}
}
}

It seems all you are doing inside your onClick is getting the item position. It is now up to you to do something with that position.
So the question comes down to, what do you want to do?
Launch a details activity/fragment to display more info? That is a typical pattern for mobile.
Intent i = new Intent(context,DetailActivity.class);
i.putExtra(Your Data);
startActivity(i);

Related

How to implement getItemViewType() for multiple layout in RecyclerView in a Movie Database app

I am creating a movie app using TMDB api, Retrofit, Gson and Glide. I have two recyclerView and two layout to inflate. But I am unable to inflate 2 layout in recyclerView adapter.
I have already implemented popular and upcoming movie list in 2 different recyclerView. But they are showing using 1 single layout. I want to inflate popular movies in one layout and upcoming movies in another layout. I can't set the condition for getItemViewType() method. How can I check for popular and upcoming movies list in getItemViewType() method and implement it on onCreateViewHolder() method of recyclerView.
MovieAdapter class:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private Context context;
private ArrayList<Movie> movieArrayList;
public MovieAdapter(Context context, ArrayList<Movie> movieArrayList) {
this.context = context;
this.movieArrayList = movieArrayList;
}
#NonNull
#Override
public MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_item, parent, false);
return new MovieViewHolder(view);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
#Override
// Set values to the list item components
public void onBindViewHolder(#NonNull MovieViewHolder holder, int position) {
holder.movieTitle.setText(movieArrayList.get(position).getOriginalTitle());
holder.rating.setText(String.valueOf(movieArrayList.get(position).getVoteAverage()));
String imagePath = "https://image.tmdb.org/t/p/w500" + movieArrayList.get(position).getPosterPath();
Glide.with(context)
.load(imagePath)
.placeholder(R.drawable.loading)
.into(holder.movieImage);
}
#Override
public int getItemCount() {
return movieArrayList == null ? 0 : movieArrayList.size();
}
public class MovieViewHolder extends RecyclerView.ViewHolder {
TextView movieTitle, rating;
ImageView movieImage;
public MovieViewHolder(#NonNull View itemView) {
super(itemView);
movieImage = itemView.findViewById(R.id.ivMovieImage);
movieTitle = itemView.findViewById(R.id.tvTitle);
rating = itemView.findViewById(R.id.tvRating);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
Movie selectedMovie = movieArrayList.get(position);
Intent intent = new Intent(context, MovieActivity.class);
intent.putExtra("movie", selectedMovie);
context.startActivity(intent);
}
}
});
}
}
}
MainActivity class:
public class MainActivity extends AppCompatActivity {
private ArrayList<Movie> popularMovie, topRatedMovie;
private RecyclerView recyclerViewPopular, recyclerViewUpcoming;
private MovieAdapter movieAdapter, upcomingAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
private static ViewPager mPager;
private static int currentPage = 0;
private static int NUM_PAGES = 0;
String[] urls = new String[] {
"https://image.tmdb.org/t/p/w500/udDclJoHjfjb8Ekgsd4FDteOkCU.jpg",
"https://image.tmdb.org/t/p/w500//2bXbqYdUdNVa8VIWXVfclP2ICtT.jpg",
"https://image.tmdb.org/t/p/w500//zfE0R94v1E8cuKAerbskfD3VfUt.jpg",
"https://image.tmdb.org/t/p/w500//lcq8dVxeeOqHvvgcte707K0KVx5.jpg",
"https://image.tmdb.org/t/p/w500//w9kR8qbmQ01HwnvK4alvnQ2ca0L.jpg"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initSlider();
getPopularMovies();
getUpcomingMovies();
swipeRefreshLayout = findViewById(R.id.swipe_layout);
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimaryDark);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
getPopularMovies();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
}, 4000);
}
});
}
public void getPopularMovies() {
MovieDataService movieDataService = RetrofitInstance.getService();
Call<MovieDBResponse> callPopular = movieDataService.getPopularMovies(this.getString(R.string.apiKey));
callPopular.enqueue(new Callback<MovieDBResponse>() {
#Override
public void onResponse(Call<MovieDBResponse> call, Response<MovieDBResponse> response) {
MovieDBResponse movieDBResponse = response.body();
if(movieDBResponse!=null && movieDBResponse.getMovies()!=null) {
popularMovie = (ArrayList<Movie>) movieDBResponse.getMovies();
showOnRecyclerView();
}
}
#Override
public void onFailure(Call<MovieDBResponse> call, Throwable t) { }
});
}
public void getUpcomingMovies() {
MovieDataService movieDataService = RetrofitInstance.getService();
Call<MovieDBResponse> callUpcoming = movieDataService.getUpcomingMovies(this.getString(R.string.apiKey));
callUpcoming.enqueue(new Callback<MovieDBResponse>() {
#Override
public void onResponse(Call<MovieDBResponse> call, Response<MovieDBResponse> response) {
MovieDBResponse movieDBResponse = response.body();
if(movieDBResponse!=null && movieDBResponse.getMovies()!=null) {
topRatedMovie = (ArrayList<Movie>) movieDBResponse.getMovies();
showOnRecyclerView();
}
}
#Override
public void onFailure(Call<MovieDBResponse> call, Throwable t) { }
});
}
private void showOnRecyclerView() {
recyclerViewPopular = findViewById(R.id.rvMovies);
recyclerViewUpcoming = findViewById(R.id.rvTopMovies);
RecyclerView.LayoutManager popularLayoutManager = new LinearLayoutManager(this);
RecyclerView.LayoutManager upcomingLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerViewUpcoming.setLayoutManager(upcomingLayoutManager);
recyclerViewPopular.setLayoutManager(popularLayoutManager);
movieAdapter = new MovieAdapter(this, popularMovie);
upcomingAdapter = new MovieAdapter(this, topRatedMovie);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
recyclerViewPopular.setLayoutManager(new GridLayoutManager(this, 2));
}else {
recyclerViewPopular.setLayoutManager(new GridLayoutManager(this, 4));
}
recyclerViewPopular.setItemAnimator(new DefaultItemAnimator());
recyclerViewUpcoming.setItemAnimator(new DefaultItemAnimator());
recyclerViewPopular.setAdapter(movieAdapter);
recyclerViewUpcoming.setAdapter(upcomingAdapter);
movieAdapter.notifyDataSetChanged();
upcomingAdapter.notifyDataSetChanged();
}
}
I want to inflate 2 different layout "movie_list_item.xml" and "upcoming_movie_list_item.xml" in onCreateViewHolder() method.
With in your adapter class(MovieAdapter) create a new constructor and add extra params of Int or enum whatever simple for you i am just giving you simple example:-
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private Context context;
private ArrayList<Movie> movieArrayList;
private int viewType;
public MovieAdapter(Context context, ArrayList < Movie > movieArrayList, int viewType) {
this.context = context;
this.movieArrayList = movieArrayList;
this.viewType=viewType;
}
#NonNull
#Override
public MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
if (viewType == 1) {
//Popular movie layout
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_item, parent, false);
} else {
//upcoming movie layout
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_item, parent, false);
}
return new MovieViewHolder(view);
}
#Override
public int getItemViewType(int position) {
if (viewType == 1)
return 1; //Popular Movie Layout
else
return 2; //Upcoming Movie Layout
// return super.getItemViewType(position);
}
#Override
// Set values to the list item components
public void onBindViewHolder(#NonNull MovieViewHolder holder, int position) {
holder.movieTitle.setText(movieArrayList.get(position).getOriginalTitle());
holder.rating.setText(String.valueOf(movieArrayList.get(position).getVoteAverage()));
String imagePath = "https://image.tmdb.org/t/p/w500" + movieArrayList.get(position).getPosterPath();
Glide.with(context)
.load(imagePath)
.placeholder(R.drawable.loading)
.into(holder.movieImage);
}
#Override
public int getItemCount() {
return movieArrayList == null ? 0 : movieArrayList.size();
}
public class MovieViewHolder extends RecyclerView.ViewHolder {
TextView movieTitle, rating;
ImageView movieImage;
public MovieViewHolder(#NonNull View itemView) {
super(itemView);
movieImage = itemView.findViewById(R.id.ivMovieImage);
movieTitle = itemView.findViewById(R.id.tvTitle);
rating = itemView.findViewById(R.id.tvRating);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
Movie selectedMovie = movieArrayList.get(position);
Intent intent = new Intent(context, MovieActivity.class);
intent.putExtra("movie", selectedMovie);
context.startActivity(intent);
}
}
});
}
}
and within your activity change on this method only
private void showOnRecyclerView() {
recyclerViewPopular = findViewById(R.id.rvMovies);
recyclerViewUpcoming = findViewById(R.id.rvTopMovies);
RecyclerView.LayoutManager popularLayoutManager = new LinearLayoutManager(this);
RecyclerView.LayoutManager upcomingLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerViewUpcoming.setLayoutManager(upcomingLayoutManager);
recyclerViewPopular.setLayoutManager(popularLayoutManager);
movieAdapter = new MovieAdapter(this, popularMovie,1);
upcomingAdapter = new MovieAdapter(this, topRatedMovie,2);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
recyclerViewPopular.setLayoutManager(new GridLayoutManager(this, 2));
} else {
recyclerViewPopular.setLayoutManager(new GridLayoutManager(this, 4));
}
recyclerViewPopular.setItemAnimator(new DefaultItemAnimator());
recyclerViewUpcoming.setItemAnimator(new DefaultItemAnimator());
recyclerViewPopular.setAdapter(movieAdapter);
recyclerViewUpcoming.setAdapter(upcomingAdapter);
movieAdapter.notifyDataSetChanged();
upcomingAdapter.notifyDataSetChanged();
}
Create layout for movie_empty_item
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private Context context;
private ArrayList<Movie> movieArrayList;
//add this two line
private static final int EMPTY_VIEW_TYPE = 0;
private static final int NORMAL_VIEW_TYPE = 1;
public MovieAdapter(Context context, ArrayList<Movie> movieArrayList) {
this.context = context;
this.movieArrayList = movieArrayList;
}
#NonNull
#Override
public MovieViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//return viewholder replace like this
if(viewType == NORMAL_VIEW_TYPE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_item, parent, false);
return new MovieViewHolder(view);
}else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_empty_item, parent, false);
return new EmptyViewHolder(view);
};
}
//getItemViewType return replace like this
#Override
public int getItemViewType(int position) {
return movieArrayList.size()>0?NORMAL_VIEW_TYPE:EMPTY_VIEW_TYPE;
}
#Override
// Set values to the list item components
public void onBindViewHolder(#NonNull MovieViewHolder holder, int position) {
holder.movieTitle.setText(movieArrayList.get(position).getOriginalTitle());
holder.rating.setText(String.valueOf(movieArrayList.get(position).getVoteAverage()));
String imagePath = "https://image.tmdb.org/t/p/w500" + movieArrayList.get(position).getPosterPath();
Glide.with(context)
.load(imagePath)
.placeholder(R.drawable.loading)
.into(holder.movieImage);
}
#Override
public int getItemCount() {
return movieArrayList.size() ? movieArrayList.size():1 ;
}
public class MovieViewHolder extends RecyclerView.ViewHolder {
TextView movieTitle, rating;
ImageView movieImage;
public MovieViewHolder(#NonNull View itemView) {
super(itemView);
movieImage = itemView.findViewById(R.id.ivMovieImage);
movieTitle = itemView.findViewById(R.id.tvTitle);
rating = itemView.findViewById(R.id.tvRating);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
Movie selectedMovie = movieArrayList.get(position);
Intent intent = new Intent(context, MovieActivity.class);
intent.putExtra("movie", selectedMovie);
context.startActivity(intent);
}
}
});
}
}
public class EmptyViewHolder extends RecyclerView.ViewHolder {
public EmptyViewHolder(#NonNull View itemView) {
super(itemView);
}
}
}

Resource not found exception while trying to add recylerview to a fragment

I'm trying to add a recyclerview to a fragment, but somehow there happens to be an error in the adapter.
I think it is the way in which I bind it, and I can't figure out the solution to it. Can anybody help me solve the issue?
here's my adapter:
public class MyLeaguesListAdapter extends
RecyclerView.Adapter<MyLeaguesListAdapter.MyViewHolder>{
List<MyContest> listItems;
Context context;
public interface OnItemClickListener {
void onItemClick(View v,int pos);
}
public MyLeaguesListAdapter(List<MyContest> listItems,Context context){
this.listItems = listItems;
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v;
v = LayoutInflater.from(context).inflate(R.layout.my_contest_item,parent,false);
MyViewHolder myViewHolder = new MyViewHolder(v);
return myViewHolder;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView leagueName,playerName,prizePool,playerRank,playerPoints,entryFee,spots;
OnItemClickListener onItemCheckListener;
public MyViewHolder(View itemView) {
super(itemView);
leagueName = (TextView) itemView.findViewById(R.id.mc_contest_name);
playerName = (TextView) itemView.findViewById(R.id.mc_player_name);
prizePool = (TextView) itemView.findViewById(R.id.mc_prize_pool);
playerRank = (TextView) itemView.findViewById(R.id.mc_player_rank);
playerPoints = (TextView) itemView.findViewById(R.id.mc_player_points);
entryFee = (TextView) itemView.findViewById(R.id.mc_entry_fee);
spots = (TextView) itemView.findViewById(R.id.mc_spots);
itemView.setOnClickListener(this);
}
public void setItemClickListener(OnItemClickListener ic){
this.onItemCheckListener = ic;
}
#Override
public void onClick(View view) {
this.onItemCheckListener.onItemClick(view,getAdapterPosition());
}
}
#Override
public int getItemCount() {
return listItems.size();
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
MyContest listItem = listItems.get(position);
holder.leagueName.setText(listItem.getLeaguename());
holder.prizePool.setText(listItem.getPrizepool());
holder.playerPoints.setText(listItem.getScore());
holder.playerRank.setText(listItem.getRank());
holder.playerName.setText(listItem.getUsername());
holder.spots.setText(listItem.getSpots());
holder.entryFee.setText(listItem.getFee());
holder.setItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(View v, int pos) {
}
});
}
}
this is my fragment:
public class MyLeagues extends Fragment {
SharedPreferences sharedPreferences,ui;
int score,userid,i=0;
String username,lname,inviteCode;
List<MyContest> list_item;
MyLeaguesListAdapter adapter;
ProgressBar progressBar;
Sprite fadingCircle;
RecyclerView recyclerView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_leagues,null);
ui = this.getActivity().getSharedPreferences("User",Context.MODE_PRIVATE);
userid = ui.getInt("userid",-1);
progressBar = (ProgressBar) view.findViewById(R.id.mcspin_kit);
fadingCircle = new FadingCircle();
progressBar.setIndeterminateDrawable(fadingCircle);
Log.d("eede", "onCreateView: "+inviteCode);
recyclerView = (RecyclerView) view.findViewById(R.id.mc_recycler);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), LinearLayoutManager.VERTICAL));
list_item = new ArrayList<>();
getMYContests();
return view;
}
public void getMYContests(){
Call<MyContestResponse> call = RetrofitClient
.getInstance()
.getApi()
.getMycontests(userid);
call.enqueue(new Callback<MyContestResponse>() {
#Override
public void onResponse(Call<MyContestResponse> call, Response<MyContestResponse> response) {
list_item=response.body().getData();
adapter = new MyLeaguesListAdapter(list_item,getContext());
progressBar.setVisibility(View.INVISIBLE);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<MyContestResponse> call, Throwable t) {
Log.d("bruv", "onFailure: "+t);
}
});
}
}
error:
07-03 09:36:20.980 30095-30095/? E/AndroidRuntime: FATAL EXCEPTION:
main
Process: com.example.android.khelo, PID: 30095
android.content.res.Resources$NotFoundException: String resource ID #0xffffffff
at android.content.res.Resources.getText(Resources.java:363)
at android.widget.TextView.setText(TextView.java:6485)
at com.example.android.khelo.MyLeaguesListAdapter.onBindViewHolder(MyLeaguesListAdapter.java:75)
at com.example.android.khelo.MyLeaguesListAdapter.onBindViewHolder(MyLeaguesListAdapter.java:20)
from what I've read, the issue is with the way I bind the recylerview but I've not got a clear idea about where the issue actually lies.
It is possible that one or many of your listItem attributes return an integer like getScore and getFee. So let's look at the implementation of TextView.setText(int)
public final void setText(int resid) {
...
}
As you can see, it only accepts the int as a resource id like R.string.something.
So what you can do here is to make your int become string when setText like
holder.playerPoints.setText(listItem.getScore().toString());

Passing data from RecyclerView.Adapter to fragment onClick

I'm trying to figure out how to get data from a clicked item in a RecyclerView to a listview in a Fragment. I can't seem to figure out how to do this, as I can't get my bundle to work.
I've tried various solutions offered here on Stackoverflow, but none of them have worked. I have managed to get the info from the recyclerview, but I am stuck trying to figure out how I can pass it to the fragment. Can someone please help me?
The Adapter class:
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder> {
private Context context;
ArrayList<FoodActivity> list;
public FoodAdapter(ArrayList<FoodActivity> list){
this.list = list;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item_food, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.foods.setText(list.get(position).getName());
holder.carbo.setText(list.get(position).getCarbohydrates());
holder.protein.setText(list.get(position).getProtein());
holder.fats.setText(list.get(position).getFats());
//Get items from recyclerview when user clicks them. Then send them to FoodFragment
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String foods = list.get(position).getName();
String carbo = list.get(position).getCarbohydrates();
String protein = list.get(position).getProtein();
String fats = list.get(position).getFats();
Toast.makeText(v.getContext(), "test: " + foods, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return list.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView foods, carbo, fats, protein;
public ViewHolder(View itemView) {
super(itemView);
carbo = itemView.findViewById(R.id.carbo);
protein = itemView.findViewById(R.id.protein);
fats = itemView.findViewById(R.id.fats);
foods = itemView.findViewById(R.id.food);
}
}
}
The Fragment where the data comes from:
public class TrackingFragment extends Fragment {
DatabaseReference databaseReference;
ArrayList<FoodActivity> list;
RecyclerView recyclerView;
SearchView searchView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tracking, container, false);
databaseReference = FirebaseDatabase.getInstance().getReference().child("foods");
recyclerView = view.findViewById(R.id.rv);
searchView = view.findViewById(R.id.searchFood);
return view;
}
#Override
public void onStart() {
super.onStart();
if(databaseReference != null){
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
list = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()){
list.add(ds.getValue(FoodActivity.class));
}
FoodAdapter adapter = new FoodAdapter(list);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getActivity(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
if(searchView != null){
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
search(newText);
return true;
}
});
}
}
private void search(String str){
ArrayList<FoodActivity> searchList = new ArrayList<>();
for(FoodActivity object : list){
if(object.getName().toLowerCase().contains(str.toLowerCase())){
searchList.add(object);
}
}
FoodAdapter foodAdapter = new FoodAdapter(searchList);
recyclerView.setAdapter(foodAdapter);
}
}
And the class where it needs to go:
public class FoodFragment extends Fragment {
ImageButton addFood;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_food, container, false);
addFood = view.findViewById(R.id.addFood);
addFood.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fr = getFragmentManager().beginTransaction();
fr.replace(R.id.fragment_container, new TrackingFragment());
fr.addToBackStack(null).commit();
}
});
return view;
}
}
The most simple is to add variables you need to your activity, set their values with onClick() and then retrieve data in other fragment:
in activity:
String foods;
public String getFoods() {
return foods;
}
public void setFoods(String foods) {
this.foods = foods;
}
in adapter:
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((YourActivity)getActivity()).setFoods("Any value");
}
});
in destination fragment:
String foods = ((YourActivity)getActivity()).getFoods();
Add an interface to your adapter as follow
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder> {
interface OnClickListener {
void onClick(FoodActivity clickedItem);
}
private OnClickListener mCallback;
private ArrayList<FoodActivity> list;
public FoodAdapter(ArrayList<FoodActivity> list){
this.list = list;
}
public void setOnClickListener(OnClickListener callback) {
mCallback = callback;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item_food, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.foods.setText(list.get(position).getName());
holder.carbo.setText(list.get(position).getCarbohydrates());
holder.protein.setText(list.get(position).getProtein());
holder.fats.setText(list.get(position).getFats());
//Get items from recyclerview when user clicks them. Then send them to FoodFragment
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCallback != null)
mCallback.onClick(list.get(position));
}
});
}
#Override
public int getItemCount() {
return list.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView foods, carbo, fats, protein;
public ViewHolder(View itemView) {
super(itemView);
carbo = itemView.findViewById(R.id.carbo);
protein = itemView.findViewById(R.id.protein);
fats = itemView.findViewById(R.id.fats);
foods = itemView.findViewById(R.id.food);
}
}
}
Android sometimes is a little complicated, when it involves the full stack:
01 RecyclerView Adapter
/** 01. Some Adapter */
public class SomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private WeakReference<Context> mContext;
/** Constructor */
public SomeAdapter(#NonNull Context context) {
this.mContext = new WeakReference<>(context);
}
#NonNull
protected Context getContext() {
return this.mContext.get();
}
/** Call to Activity from within the adapter. */
private void someMethod() {
SomeActivity activity = (SomeActivity) getContext();
synchronized(activity) {activity.showLoginDialog();}
}
}
02 AppCompatActivity
/** 02. Some Activity */
public class SomeActivity extends AppCompatActivity {
#Nullable
private BaseFragment currentFragment = null;
/** Constructor */
public SomeActivity() {}
public void setCurrentFragment(Fragment fragment) {
this.currentFragment = fragment;
}
/** Call to the current Fragment. */
public void someMethod() {
if (currentFragment != null) {
currentFragment.someMethod();
}
}
}
03 Fragment
/** Some Fragment */
public class SomeFragment extends Fragment {
/** Constructor */
public SomeFragment() {}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
((BaseActivity) context).setCurrentFragment(this);
}
#Override
public void onDetach() {
super.onDetach();
((BaseActivity) getActivity()).setCurrentFragment(this);
}
}
To get your data from FoodAdapter to TrackingFragment, you can add TrackingFragment (or an interface it implements, ideally) as a parameter to the FoodAdapter constructor, then use that instance to forward your ViewHolder clicks to TrackingFragment for handling.
To get your data from TrackingFragment to FoodFragment, use the setTargetFragment/onActivityResult pattern for fragment <-> fragment communication. This answer has an example: https://stackoverflow.com/a/13733914/3238938

Using ParseRecyclerQueryAdapter

Please I would like someone to help point me in the right direction with using the ParseRecyclerQueryAdapter. I'm trying to retrieve articles with my current adapter class that implements the standard RecyclerView. my implementation of pagination is not working properly soIi would like a demonstration from anyone that has used the ParseRecyclerQueryAdapter to achieve the following. By translating it from me so I get the implementation.
public class ArticleRVAdapter extends RecyclerView.Adapter {
List<Article> articleData = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
public ArticleRVAdapter(Context context, List<Article> data){
inflater=LayoutInflater.from(context);
this.articleData= data;
this.context = context;
}
#Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.article_item, parent, false);
ArticleViewHolder viewHolder = new ArticleViewHolder(view);
return viewHolder;
}
#Override
public int getItemCount() {
return articleData.size();
}
public class ArticleViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
CardView cardView;
TextView title;
TextView body;
Date dateCreated;
TextView author;
ImageView headImage;
String objectId;
public ArticleViewHolder(final View itemView) {
super(itemView);
itemView.setClickable(true);
itemView.setLongClickable(true);
itemView.setOnClickListener(this);
cardView = (CardView) itemView.findViewById(R.id.card_article);
title = (TextView) itemView.findViewById(R.id.text_title);
body = (TextView) itemView.findViewById(R.id.text_article_body);
//dateCreated = itemView.findViewById(R.id.text_article_body);
author = (TextView) itemView.findViewById(R.id.text_author);
headImage = (ImageView) itemView.findViewById(R.id.imageView_thumb);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), ArticleInformationActivity.class);
intent.putExtra("article_id", articleData.get(getLayoutPosition()).getObjectId());
intent.putExtra("article_title", articleData.get(getLayoutPosition()).getArticleTitle());
intent.putExtra("article_body", articleData.get(getLayoutPosition()).getArticleBody());
intent.putExtra("article_author", articleData.get(getLayoutPosition()).getArticleAuthor());
intent.putExtra("article_date", articleData.get(getLayoutPosition()).getDateCreated());
v.getContext().startActivity(intent);
}
}
After a lot of testing, I got the solution in my project:
Fragment (or Activity):
private RecyclerView mRecyclerView;
private MyQueryAdapter myQueryAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.rv);
myQueryAdapter = new MyQueryAdapter(true);
mRecyclerView.setAdapter(myQueryAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
myQueryAdapter.addOnQueryLoadListener(new ParseRecyclerQueryAdapter.OnQueryLoadListener<MY_MODEL>() {
#Override
public void onLoaded(List<MY_MODEL> objects, Exception e) {
if (swipeRefreshLayout.isRefreshing()) {
swipeRefreshLayout.setRefreshing(false);
}
}
#Override
public void onLoading() {
if (!swipeRefreshLayout.isRefreshing()) {
swipeRefreshLayout.setRefreshing(true);
}
}
});
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
myQueryAdapter.loadObjects();
}
});
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onResume() {
super.onResume();
myQueryAdapter.loadObjects();
}
Adapter
public class MyQueryAdapter extends ParseRecyclerQueryAdapter<MY_MODEL, MyQueryAdapter.MyViewHolder>{
public MyQueryAdapter(boolean hasStableIds) {
super(MY_MODEL.class, hasStableIds);
}
public MarcacionesAdapter(ParseQueryAdapter.QueryFactory<Marcaciones> factory, boolean hasStableIds) {
super(factory, hasStableIds);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(v);
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MY_MODEL model = getItem(position);
holder.name.setText(model.getName());
holder.year.setText(model.getYear());
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView name;
TextView year;
MyViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.card_view);
name = (TextView)itemView.findViewById(R.id.name);
year = (TextView)itemView.findViewById(R.id.year);
}
}
}
If you want to configure a custom query, you can do it in this way:
factory =
new ParseQueryAdapter.QueryFactory<MY_MODEL>() {
public ParseQuery< MY_MODEL > create() {
ParseQuery<MY_MODEL> query = MY_MODEL.getQuery();
query.include("user");
//Filter by date
query.whereGreaterThan("createdAt", midnight);
query.whereLessThan("createdAt", now);
query.orderByDescending("createdAt");
return query;
}
};
adapter = new MyQueryAdapter(factory, true);

Update RecycleView from Fragment?

I'm trying to add an Object to this RecycleView. When I add the objects to the initial ArrayList they all show up. However, when I try to add an object and call notifyDataSetChanged from HomeFragment, nothing happens on the UI.
HomeFragment.java
public class HomeFragment extends Fragment {
View myView;
private RecyclerView mRecyclerView;
private HomeAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private ArrayList<Note> myNotes;
private Activity activity;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
myView = inflater.inflate(R.layout.first_layout, container, false);
mRecyclerView = (RecyclerView) myView.findViewById(R.id.list12313);
//linear layout manager
mLayoutManager = new LinearLayoutManager(activity);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//adapter
myNotes = new ArrayList<Note>();
myNotes.add(new Note("Welcome to WITS Mobile", "Logged in as: " + LoginActivity.witsName));
myNotes.add(new Note("Version 0.1 ALPHA", "- Early Internal Alpha"));
//myNotes.add(new Note());
mAdapter = new HomeAdapter(myNotes, activity);
mRecyclerView.setAdapter(new SlideInBottomAnimationAdapter(mAdapter));
setHasOptionsMenu(true);
return myView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.first, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId())
{
case R.id.action_add:
addItem();
return true;
case R.id.action_CLR:
clear();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void addItem()
{
Note e = new Note("New Title", "New Body");
mAdapter.addItem(e);
}
public void clear()
{
mAdapter.clear();
}
}
HomeAdapter.java
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder>
{
private ArrayList<Note> mNotes;
private int lastPosition = -1;
private Context context;
public HomeAdapter(ArrayList<Note> list, Context context)
{
this.mNotes = list;
this.context = context;
}
public void clear()
{
mNotes.clear();
notifyDataSetChanged();
}
public void addItem(Note n)
{
System.out.println("add");
mNotes.add(n);
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder
{
public View view;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
}
}
public HomeAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
//create new view
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_card, viewGroup, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
public TextView title;
public TextView subtext;
#Override
public void onBindViewHolder(HomeAdapter.ViewHolder viewHolder, int i)
{
//Replace contents of a view, called by layout manager
title = (TextView) viewHolder.view.findViewById(R.id.title);
subtext = (TextView) viewHolder.view.findViewById(R.id.subtext);
title.setText(mNotes.get(i).getTitle());
subtext.setText(mNotes.get(i).getBody());
setAnimation(viewHolder.view, i);
}
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return mNotes.size();
}
}
Take out this line:
mRecyclerView.setHasFixedSize(true);
Fixed size means the count of the items, not the layout size

Categories

Resources