RecyclerView、Adapter和ViewHolder

本文详细介绍了RecyclerView作为ListView升级版的优势,如解决ListView性能问题及单一纵向滚动限制。解释了ViewHolder模式及其实现方式,展示了如何通过Adapter连接数据源与RecyclerView,包括创建ViewHolder、绑定数据到ViewHolder的具体代码示例。

RecyclerView是ListView的升级版,强化了ListView的某些不足。比如listView如果不使用一些技巧的话,listView的性能就会非常差;ListView只能实现纵向滚动的效果等。

顾名思义,ViewHolder只做一件事:容纳View视图

RecyclerView自身是不会创建视图,它创建的是ViewHolder,而ViewHolder引用这一个个itemView

如下图:


RecyclerView自己不会创建ViewHolder。这个任务实际是由adapter来完成的。adapter是个控制器对象,从模型层获取数据,然后提供给RecyclerView显示,起到桥梁的作用。

adapter负责:

1:创建必要的ViewHolder

2:绑定ViewHolder至模型层数据

recyclerView需要显示视图时,就会去找它的adapter。下图展示了一个recyclerView可能发起的会话。


首先,通过调用adapter的getItemCount()方法,RrecyclerView询问数组列表中包含多少个对象

接着,RecyclerView调用adapter的CreateViewHolder()方法创建ViewHolder以及ViewHolder要显示的视图。

最后,RecyclerView会传入ViewHolder及其位置,调用onBindViewHolder(ViewHolder,int position)方法。adapter会找到目标位置的数据并更新到ViewHolder的视图上。

具体代码如下;

private class CrimeHolder extends RecyclerView.ViewHolder 
        implements View.OnClickListener {

    private TextView mTitleTextView;
    private TextView mDateTextView;
    private CheckBox mSolvedCheckBox;

    private Crime mCrime;

    public CrimeHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);

        mTitleTextView = (TextView) itemView.findViewById(R.id.list_item_crime_title_text_view);
        mDateTextView = (TextView) itemView.findViewById(R.id.list_item_crime_date_text_view);
        mSolvedCheckBox = (CheckBox) itemView.findViewById(R.id.list_item_crime_solved_check_box);
    }

    public void bindCrime(Crime crime) {   //在viewholder中实现的,所以还是可以说viewholder只是容纳视图
        mCrime = crime;
        mTitleTextView.setText(mCrime.getTitle());
        mDateTextView.setText(mCrime.getDate().toString());
        mSolvedCheckBox.setChecked(mCrime.isSolved());
    }

    @Override
    public void onClick(View v) {
        mCallbacks.onCrimeSelected(mCrime);
    }
}

private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {

    private List<Crime> mCrimes;

    public CrimeAdapter(List<Crime> crimes) {
        mCrimes = crimes;
    }

    @Override
    /*
    锁定视图R.layout.list_item_crime,绑定到ViewHolderCrimeHolder继承ViewHolder)中
     */
    public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        View view = layoutInflater.inflate(R.layout.list_item_crime, parent, false);
        return new CrimeHolder(view);
    }

    @Override
    /*
    viewHolder中的布局添加数据c
     */
    public void onBindViewHolder(CrimeHolder holder, int position) {
        Crime crime = mCrimes.get(position);
        holder.bindCrime(crime);
    }

    @Override
    public int getItemCount() {
        return mCrimes.size();
    }

    public void setCrimes(List<Crime> crimes) {
        mCrimes = crimes;
    }
}


搞定了adapter,最后要做的就是将它和RecyclerView关联起来,该方法创建adapter,然后设置给RecyclerView。代码如下所示

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_crime_list, container, false);

    mCrimeRecyclerView = (RecyclerView) view
            .findViewById(R.id.crime_recycler_view);
    mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    if (savedInstanceState != null) {
        mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);//得到saveInstanceState的值
    }

    updateUI();

    return view;
}

public void updateUI() {
    CrimeLab crimeLab = CrimeLab.get(getActivity());//得到CrimeLab对象
    List<Crime> crimes = crimeLab.getCrimes();//得到list对象

  
        mAdapter = new CrimeAdapter(crimes);//list对象添加到Adapter        mCrimeRecyclerView.setAdapter(mAdapter);//启用这个adapter


}


public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private final AppIconAdapter mAdapter; public SimpleItemTouchHelperCallback(AppIconAdapter adapter) { mAdapter = adapter; } @Override public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); // 拖动开始时设置透明度 if (actionState == ItemTouchHelper.ACTION_STATE_DRAG && viewHolder != null) { viewHolder.itemView.setAlpha(0.5f); // 设置半透明效果 } } @Override public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); // 拖动结束时恢复透明度 viewHolder.itemView.setAlpha(1.0f); // 关键恢复代码 } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { if (viewHolder.getAdapterPosition() == 0) { return makeMovementFlags(0, 0); } int dragFlags; if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } else { dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; } return makeMovementFlags(dragFlags, 0); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { if ((viewHolder.getAdapterPosition() == 0 || target.getAdapterPosition() == 0)) { return false; } mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } } 当前页面如果支持翻页的话是否支持该拖拽换位功能
最新发布
07-31
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值