2015-11-15 2 views
8

Я читаю пример кода от Google, код выглядит так:должен ли держатель удерживать ссылку на адаптер?

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); 
} 

}

Вы можете видеть каждый ViewHolder содержит ссылку (ItemClickListener) к адаптеру, так как адаптер сохраняет ссылку на ViewHolder уже, кто-нибудь знает, может ли такая реализация вызвать утечку памяти? Пожалуйста, поправьте меня, если мое понимание ошибочно.

ответ

0

Не думайте, что это будет. ViewHolder не может существовать без адаптера и будет собирать мусор задолго до адаптера, так как ViewHolders постоянно перерабатываются адаптером при прокрутке RecyclerView. Используемый шаблон интерфейса является всего лишь обычным способом уведомления адаптера о том, что был выбран какой-либо объект ViewHolder. Я полагаю, вы могли бы утечки памяти, если вы делаете обратное, удерживая ссылку на определенный объект ViewHolder в переменной-члене внутри адаптера, поскольку это может помешать представлению ViewGolder для GC'd. Тем не менее, приведенный выше код кажется довольно стандартным.