Set onclicklistener in recyclerview - java

My adaptor class:
public class Adaptor extends RecyclerView.Adapter<Adaptor.Holder>{
private ArrayList<Winkel> winkels;
private LayoutInflater inflater;
private ImageView icon;
private ItemCLickCallback itemCLickCallback;
public interface ItemCLickCallback {
void onItemClick(int p);
void onSecItemClick(int p);
}
public void setItemCLickCallback(final ItemCLickCallback itemCLickCallback1){
;this.itemCLickCallback = itemCLickCallback;
}
public Adaptor (ArrayList<Winkel> winkels,Context c){
this.inflater = LayoutInflater.from(c);
this.winkels = winkels;
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.list_item,parent,false);
return new Holder(view);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
Winkel winkel = winkels.get(position);
holder.title.setText(winkel.getNaam());
if (winkel.isFavourtite()){
holder.icon.setImageResource(R.drawable.ic_star_black_18dp);
}
else{
holder.icon.setImageResource(R.drawable.ic_star_border_black_18dp);
}
}
#Override
public int getItemCount() {
return winkels.size();
}
class Holder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TextView title;
private View container;
private ImageView icon;
public Holder(View itemView) {
super(itemView);
title = (TextView)itemView.findViewById(R.id.lbl_item_text);
container = itemView.findViewById(R.id.cont_item_root);
icon = (ImageView) itemView.findViewById(R.id.im_item_icon_secondary);
icon.setOnClickListener(this);
container.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.cont_item_root){
itemCLickCallback.onItemClick(getAdapterPosition());
}
else{
itemCLickCallback.onSecItemClick(getAdapterPosition());
}
}
}
}
#Override
public void onClick(View v) {
}
}
}
Code where it gets implemented (my issue is here at adaptor.setItemClickCallback(context)
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Adaptor adaptor = new Adaptor(winkels,context);
recyclerview.setLayoutManager(new LinearLayoutManager(context));
recyclerview.addItemDecoration(new VerticalSpace(30));
recyclerview.setAdapter(adaptor);
adaptor.setItemCLickCallback(context);
}
Called from fragment overview:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_overview, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycle);
ODKortrijkWebservice webs = new ODKortrijkWebservice(this.getActivity(),mRecyclerView);
webs.execute();
return view;
}
How do I set the context for ItemCLickCallback(this)? It should be context (at least I think so?) because that's what gets passed from the fragment but I can't seem to figure out how to get this to work, so some help would be appreciated. Basically I want to add onclicklisteners for every item in my recyclerview, and the recyclerview is created by using data from a webservice, hence why the adaptor class is called from the class where I get the data from the web service, which gets excecuted in my fragment. Thank you.

I recommend you to make ODKortrijkWebservice.Callback like following.
In your ODKortrijkWebservice:
public class ODKortrijkWebservice extends AsyncTask<...> {
private Callback mCallback;
public interface Callback {
void onSuccess(ArrayList<Winkel> winkels);
}
public ODKortrijkWebservice(Context context, Callback callback) {
...
mCallback = callback;
...
}
#Override
protected void onPostExecute(Void aVoid) {
...
mCallback.onSuccess(winkels);
}
}
In your Fragment:
public class YourFragment extends Fragment implements ODKortrijkWebservice.Callback, Adaptor.ItemCLickCallback {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_overview, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycle);
ODKortrijkWebservice webs = new ODKortrijkWebservice(this.getActivity(), this);
webs.execute();
return view;
}
#Override
public void onSuccess(ArrayList<Winkel> winkels) {
Adaptor adaptor = new Adaptor(winkels, getContext());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.addItemDecoration(new VerticalSpace(30));
mRecyclerView.setAdapter(adaptor);
adaptor.setItemCLickCallback(this);
}
#Override
public void onItemClick(int p) {
}
#Override
public void onSecItemClick(int p) {
}
}

Here,
You need to create one interface at RecycleView.Adapter<>
private static OnItemClickListener listener;
// Define the listener interface
public interface OnItemClickListener {
void onItemClick(View itemView, int position);
}
// Define the method that allows the parent activity or fragment to define the listener
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
send require details with interface method
public class ViewHolder extends RecyclerView.ViewHolder{
TextView header_title;
public ViewHolder(final View itemView) {
super(itemView);
txt_country_name = (TextView)itemView.findViewById(R.id.header_title);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Triggers click upwards to the adapter on click
if (listener != null)
listener.onItemClick(itemView, getLayoutPosition());
}
});
}
}
call adapter listener
ListAdapter listAdapter;
listAdapter.setOnItemClickListener(new listAdapter.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Toast.makeText(getActivity(), position+ " was clicked!", Toast.LENGTH_SHORT).show();
}
});

Related

How to setOnClickListener in adapter using RecyclerView to display inside fragment

I cannot access the ID of the item to view it in ToastMessage, or even store it in the database (use Room DataBase)
I have tried but the message does not appear
I need the reference ID to use for database storage and complete the process for storing the shopping cart
itemAdapter.java
public class itemAdapter extends RecyclerView.Adapter<itemAdapter.ItemViewHolder> {
private Context context;
private ArrayList<Items> arrayList;
private AdapterView.OnItemClickListener listener;
public itemAdapter(Context context, ArrayList<Items> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
return new ItemViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
holder.name.setText(arrayList.get(position).getItemName());
holder.desc.setText(arrayList.get(position).getItemDesc());
holder.price.setText(arrayList.get(position).getItemPrice());
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,arrayList.get(position).getItemIid(),Toast.LENGTH_SHORT);
}
});
holder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,arrayList.get(position).getItemPrice(),Toast.LENGTH_SHORT);
}
});
}
#Override
public int getItemCount() {
return arrayList.size();
}
class ItemViewHolder extends RecyclerView.ViewHolder {
TextView name, desc, price;
ImageView remove, add;
public ItemViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.tvName);
desc = itemView.findViewById(R.id.tvDesc);
price = itemView.findViewById(R.id.tvPrice);
remove = itemView.findViewById(R.id.btnDelete);
add = itemView.findViewById(R.id.btnAdd);
}
}
}
MealsFragment.java
public class MealsFragment extends Fragment {
public MealsFragment() {
// Required empty public constructor
}
RecyclerView recyclerView;
itemAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_meals, container, false);
}
#Override
public void onViewCreated( View view, Bundle savedInstanceState) {
ArrayList<Items> ItemsList = (ArrayList<Items>) RoomDatabaseSingleton.getInstance(getContext().getApplicationContext())
.getAppDatabase()
.getDao()
.getItems("meals");
recyclerView = view.findViewById(R.id.rvMeals);
RecyclerView.LayoutManager manager = new LinearLayoutManager(
getContext(), RecyclerView.VERTICAL, false);
recyclerView.setLayoutManager(manager);
adapter = new itemAdapter(getContext(), ItemsList);
recyclerView.setAdapter(adapter);
}
}
Try the following instead
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,arrayList.get(position).getItemIid(),Toast.LENGTH_SHORT).show();
}
});
holder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,arrayList.get(position).getItemPrice(),Toast.LENGTH_SHORT).show();
}
});
The static method makeText of Toast is used to create the Toast object and show() method on the Toast object is used to display the Toast

Recyclerview los data when rotate display , data is load when push button Android

sorry for my bad english
My problem: when I rotate my application, all data is lost, I am using a ViewModel, my data loads when I push the button, this is my code for test .
https://github.com/elviss116/androidMvvm-master
This is the Fragment :
public class MovieListFragment extends Fragment {
private MovieListViewModel mViewModel;
private List<MovieModel.DataModel> movieList = new ArrayList<>();
private RecyclerView recyclerView;
private MoviesAdapter mAdapter;
private Button cargar;
public static MovieListFragment newInstance() {
return new MovieListFragment();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.movie_list_fragment, container, false);
recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
cargar = view.findViewById(R.id.btnCargar);
mAdapter = new MoviesAdapter(movieList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
cargar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mViewModel = ViewModelProviders.of(MovieListFragment.this).get(MovieListViewModel.class);
mViewModel.init();
mViewModel.getMovies().observe(MovieListFragment.this, new Observer<MovieModel>() {
#Override
public void onChanged(#Nullable MovieModel movieModels) {
movieList.addAll(movieModels.getData());
mAdapter.notifyDataSetChanged();
}
});
}
});
}
}
this is the ViewModel :
public class MovieModel {
#SerializedName("data")
List<DataModel> data;
public List<DataModel> getData() {
return data;
}
public void setData(List<DataModel> data) {
this.data = data;
}
public class DataModel {
#SerializedName("name")
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
this is the adapter :
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {
private List<MovieModel.DataModel> moviesList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
}
}
public MoviesAdapter(List<MovieModel.DataModel> moviesList) {
this.moviesList = moviesList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.movie_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MovieModel.DataModel movie = moviesList.get(position);
holder.name.setText(movie.getName());
}
#Override
public int getItemCount() {
return moviesList.size();
}
}
When you rotate your phone the activity gets destroyed and re-created, so that is why you're seeing your data dissapear.
What I would recommend is grabbing and observing the view model when the activity is created, outside of the click listener. This way the fragment will immediately start observing the data when it is rotated, but will only be initialized when the button is clicked.
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(MovieListFragment.this).get(MovieListViewModel.class);
mViewModel.getMovies().observe(MovieListFragment.this, new Observer<MovieModel>() {
#Override
public void onChanged(#Nullable MovieModel movieModels) {
movieList.addAll(movieModels.getData());
mAdapter.notifyDataSetChanged();
}
});
cargar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mViewModel.init();
}
});
}

Handling onClicks of RecyclerView inside a Fragment

I am trying to implement RecyclerView inside a Fragment. I have designed a CustomAdapter(StateAdapter) class to load the contents of RecyclerView and an interface StateAdapterOnClickHandler to handle onClicks of the items inside RecyclerView but clicking on item doesn't work.
Here's my HomeFragment.java which extends Fragment. I am unable to figure out how to initialize the StateAdapterOnClickHandler and where to call its method onItemClick()
public class HomeFragment extends Fragment implements StateAdapter.StateAdapterOnClickHandler {
private View homeFragment;
private RecyclerView recyclerView;
private StateAdapter stateAdapter;
private List<String> states;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public static HomeFragment newInstance() {
HomeFragment homeFragment = new HomeFragment();
return homeFragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
homeFragment = inflater.inflate(R.layout.fragment_home,container,false);
recyclerView = homeFragment.findViewById(R.id.recyclerview_states);
states = Arrays.asList(getResources().getStringArray(R.array.india_states));
LinearLayoutManager layoutManager = new LinearLayoutManager(container.getContext(),LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
stateAdapter = new StateAdapter();
stateAdapter.setStateNames(states);
recyclerView.setAdapter(stateAdapter);
return homeFragment;
}
#Override
public void onItemClick(String state) {
Intent intent = new Intent(getActivity(),DetailActivity.class);
intent.putExtra("State",state);
startActivity(intent);
}
}
Here's my StateAdapter class
public class StateAdapter extends RecyclerView.Adapter<StateAdapter.StateViewHolder> {
private List<String> stateNames;
private final StateAdapterOnClickHandler stateAdapterOnClickHandler;
StateAdapter(StateAdapterOnClickHandler stateAdapterOnClickHandler){
this.stateAdapterOnClickHandler = stateAdapterOnClickHandler;
}
public interface StateAdapterOnClickHandler {
void onItemClick(String state);
}
#Override
public StateAdapter.StateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
int idForListItem = R.layout.state_layout;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(idForListItem,parent,false);
return new StateViewHolder(view);
}
#Override
public void onBindViewHolder(StateAdapter.StateViewHolder holder, int position) {
String stateName = stateNames.get(position);
holder.mTextView.setText(stateName);
}
#Override
public int getItemCount() {
if(stateNames == null) return 0;
return stateNames.size();
}
public class StateViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView mTextView;
public StateViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.tv_state_name);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int clickedPostion = getAdapterPosition();
String state = stateNames.get(clickedPostion);
stateAdapterOnClickHandler.onItemClick(state);
}
}
public void setStateNames(List<String> states) {
stateNames = states;
notifyDataSetChanged();
}
}
Please, tell me what's wrong with the code while handling the clicks. I am new to Android Programming and this is first time I am working with Fragments. Thanks for helping.

viewpager with tab fragments with recyclerview just show first item from database

The title say it all but just in case my problem is that i have a viewpager with two tabs, one with a recyclerview that fetch the data from a sqlite database but just show the first entry but i have created more.
this is my recyclerview adapter
public class RecyclerViewMessagesAdapter extends RecyclerView.Adapter<RecyclerViewMessagesAdapter.TextMessagesViewHolder>{
private DatabaseHandler databaseHandler;
private Context context;
public RecyclerViewMessagesAdapter(Context context){
this.context = context;
databaseHandler = new DatabaseHandler(context);
}
#Override
public int getItemCount() {
return databaseHandler.getAllTextMessage().size();
}
#Override
public TextMessagesViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_messages, parent, false);
TextMessagesViewHolder textMessagesViewHolder = new TextMessagesViewHolder(view);
return textMessagesViewHolder;
}
public static class TextMessagesViewHolder extends RecyclerView.ViewHolder {
TextView textviewPhoneNumber, textviewDate;
TextMessagesViewHolder(View itemView) {
super(itemView);
textviewPhoneNumber = (TextView)itemView.findViewById(R.id.textview_recyclerview_phone_number);
textviewDate = (TextView)itemView.findViewById(R.id.textview_recyclerview_date_to_send);
}
}
#Override
public void onBindViewHolder(TextMessagesViewHolder holder, int position) {
holder.textviewPhoneNumber.setText(databaseHandler.getMessage(position+1).getPhoneNumber());
holder.textviewDate.setText(String.valueOf(databaseHandler.getMessage(position+1).getDate()));
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
and this is the fragment class with the recyclerview.
public class FragmentHistoryTab extends Fragment{
private View rootView;
private DatabaseHandler databaseHandler;
private TextView textviewEmptySavings;
private RecyclerView messagesRecyclerView;
private OnFragmentInteractionListener mListener;
public FragmentHistoryTab() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_history_tab,container,false);
return rootView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
databaseHandler = new DatabaseHandler(getContext());
textviewEmptySavings = (TextView)rootView.findViewById(R.id.textview_empty_recyclerview);
RecyclerViewMessagesAdapter adapter = new RecyclerViewMessagesAdapter(getContext());
messagesRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview_saved_messages);
messagesRecyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
messagesRecyclerView.setLayoutManager(layoutManager);
messagesRecyclerView.setAdapter(adapter);
if (databaseHandler.getAllTextMessage().size() >= 1){
textviewEmptySavings.setVisibility(View.GONE);
messagesRecyclerView.setVisibility(View.VISIBLE);
}else {
textviewEmptySavings.setVisibility(View.VISIBLE);
messagesRecyclerView.setVisibility(View.GONE);
}
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public interface OnFragmentInteractionListener {
}
}
thanks in advance!
i don't know what happened but it just fixed all alone.

RecylerView Adapter causing memory leak when using on Click interface

In my RecyclerView.Adapter I have defined this interface:
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
The Fragment which contains the RecyclerView implements this interface.
After 4 or 5 orientation changes LeakCanary reports a memory leak:
My Fragment looks like this:
public class ImagesFragment extends Fragment implements ImageAdapter.OnItemClickListener {
private static final String IMAGES_FRAGMENT_TAG = "ImagesFragment";
private int SPAN_COUNT = 2;
private String categoryName;
private String categoryURL;
private int ImageCount;
protected RecyclerView mRecyclerView;
protected RecyclerView.LayoutManager mLayoutManager;
protected static ImageAdapter mAdapter;
#Override
public void onItemClick(View view, int position) {
Toast.makeText(mContext, "Clicked:" + String.valueOf(position), Toast.LENGTH_SHORT).show();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
this.categoryName = args.getString("category");
this.categoryURL = args.getString("URL");
this.ImageCount = args.getInt("Count");
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.images_recycler_view, container, false);
rootView.setTag(IMAGES_FRAGMENT_TAG);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.imagesRecyclerView);
mRecyclerView.addItemDecoration(new CategoryItemDecoration(px, SPAN_COUNT, mCurrentLayoutType));
mLayoutManager = new GridLayoutManager(getActivity().getApplicationContext(), SPAN_COUNT);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new ImageAdapter(categoryURL, this.ImageCount, this);
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(IMAGES_FRAGMENT_TAG, IMAGES_FRAGMENT_TAG);
super.onSaveInstanceState(outState);
}
#Override
public void onDestroyView() {
super.onDestroyView();
System.out.println("OnDestroyView");
if (mRecyclerView != null) {
mRecyclerView.setAdapter(null);
}
}
#Override
public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = MyApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
My Adapter:
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImagesViewHolder> {
private static final String IMAGES_FRAGMENT_TAG = "ImagesFragment";
private Context mContext;
private static OnItemClickListener onItemClickListener;
private Integer imageCount;
public ImageAdapter(String url, Integer imageCount, OnItemClickListener itemListener) {
this.ROOTURL = url;
this.imageCount = imageCount;
this.onItemClickListener = itemListener;
}
#Override
public int getItemCount() {
return imageCount;
}
#Override
public ImagesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
this.mContext = parent.getContext();
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.images_viewitem, parent, false);
ImagesViewHolder imagesViewHolder = new ImagesViewHolder(v);
return imagesViewHolder;
}
#Override
public void onBindViewHolder(final ImagesViewHolder holder, int position) {
Glide.with(mContext)
.load("URL")
.asBitmap()
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(new BitmapImageViewTarget(holder.image) {
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
Log.e(IMAGES_FRAGMENT_TAG, "on load failed");
}
#Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
super.onResourceReady(bitmap, glideAnimation);
holder.image.setImageBitmap(bitmap);
}
});
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public static class ImagesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private static final int PALETTE_SIZE = 24;
CardView cv;
ImageView image;
RelativeLayout mImageViewWrapper;
ImagesViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.imagesCardView);
image = (ImageView) itemView.findViewById(R.id.images_ImageView);
mImageViewWrapper = (RelativeLayout) itemView.findViewById(R.id.Images_imageViewWrapper);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(v, this.getLayoutPosition());
}
}
}
Your problem is this line in your Fragment:
protected static ImageAdapter mAdapter;
And this line in your Adapter:
private static OnItemClickListener onItemClickListener;
NEVER use static for variables. Just don't do it unless you really know what you are doing. The static keyword causes your ImageAdapter and OnClickListener to stick around after the Fragment is garbage collected. It means that the variable mAdapter is not part of any instance of your Fragment but instead part of the class itself - which of course is an instant memory leak! Remove those and you should be fine.
And by the way you could have figured this out by yourself fairly quickly. Look again at the LeakCanary output:
It says that the static variable onItemClickListener in the ImageAdapter leaks an ImagesFragment instance - or in other words exactly what I am telling you in this answer.
Also you should read this answer to learn more about memory leaks.

Categories