I am reading the sample code from Google, the code is like this:
public class AttractionListFragment extends Fragment {
...
private class AttractionAdapter extends RecyclerView.Adapter<ViewHolder>
implements ItemClickListener {
public List<Attraction> mAttractionList;
private Context mContext;
public AttractionAdapter(Context context, List<Attraction> attractions) {
super();
mContext = context;
mAttractionList = attractions;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d("TEST", "onCreateViewHolder");
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_row, parent, false);
return new ViewHolder(view, this);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Attraction attraction = mAttractionList.get(position);
holder.mTitleTextView.setText(attraction.name);
holder.mDescriptionTextView.setText(attraction.description);
Glide.with(mContext)
.load(attraction.imageUrl)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.placeholder(R.drawable.empty_photo)
.override(mImageSize, mImageSize)
.into(holder.mImageView);
String distance =
Utils.formatDistanceBetween(mLatestLocation, attraction.location);
if (TextUtils.isEmpty(distance)) {
holder.mOverlayTextView.setVisibility(View.GONE);
} else {
holder.mOverlayTextView.setVisibility(View.VISIBLE);
holder.mOverlayTextView.setText(distance);
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return mAttractionList == null ? 0 : mAttractionList.size();
}
@Override
public void onItemClick(View view, int position) {
View heroView = view.findViewById(android.R.id.icon);
DetailActivity.launch(
getActivity(), mAdapter.mAttractionList.get(position).name, heroView);
}
}
private static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
TextView mTitleTextView;
TextView mDescriptionTextView;
TextView mOverlayTextView;
ImageView mImageView;
ItemClickListener mItemClickListener;
public ViewHolder(View view, ItemClickListener itemClickListener) {
super(view);
mTitleTextView = (TextView) view.findViewById(android.R.id.text1);
mDescriptionTextView = (TextView) view.findViewById(android.R.id.text2);
mOverlayTextView = (TextView) view.findViewById(R.id.overlaytext);
mImageView = (ImageView) view.findViewById(android.R.id.icon);
mItemClickListener = itemClickListener;
view.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(v, getAdapterPosition());
}
}
interface ItemClickListener {
void onItemClick(View view, int position);
}
}
You can see every ViewHolder holds a reference (ItemClickListener) to the adapter, since the adapter keeps reference to the ViewHolder already, does anyone know if this kind of implementation would cause memory leak? Please correct me if my understanding is wrong.
Don't think it would. The ViewHolder cannot exist without the Adapter, and will be garbage collected well before the Adapter is, since the ViewHolders are constantly being recycled by the Adapter as the RecyclerView is scrolled. The interface pattern being used is just a common way of notifying the Adapter that a certain ViewHolder has been clicked. I suppose you could leak memory if you do the opposite by holding a reference to a specific ViewHolder in a member variable inside the Adapter since that could prevent the ViewHolder from being GC'd. Nevertheless, the above code seems pretty standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With