视图持有者是否应该引用适配器?

时间:2015-11-15 17:33:16

标签: android android-fragments android-viewholder

我正在阅读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的引用,有没有人知道这种实现是否会导致内存泄漏?如果我的理解是错误的,请纠正我。

1 个答案:

答案 0 :(得分:0)

不要以为会这样。 ViewHolder在没有适配器的情况下不能存在,并且在适配器之前就会被垃圾收集,因为随着RecyclerView的滚动,ViewHolders会不断被适配器回收。正在使用的接口模式只是通知适配器已单击某个ViewHolder的常用方法。我想如果你通过在适配器内部的成员变量中保持对特定ViewHolder的引用来执行相反的操作,则可能会泄漏内存,因为这可能会阻止ViewHolder进行GC。不过,上面的代码似乎很标准。