RecyclerView

本文深入探讨了RecyclerView的使用方法及CursorAdapter的工作原理,详细解释了如何通过CursorAdapter结合RecyclerView展示数据,同时解决了SimpleCursorAdapter构造函数中flags参数的选择困惑。

RecyclerView优秀文集

RecyclerView.ViewHolder

ViewHolder

RecyclerView.Adapter

RecyclerView.Adapter

LayoutManager

LinearLayoutManager

GridLayoutManager

StaggeredGridLayoutManager

LayoutManager

RecyclerView.ItemDecoration

RecyclerView.ItemAnimator

DefaultItemAnimator

ItemTouchHelper

SnapHelper

RecyclerView.RecycledViewPool

CursorAdapter

hold a CursorAdapter member in my recyclerView.Adapter implementation. Then passing all the handling of creating the new view & binding it to the cursor adapter

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder> {

    // Because RecyclerView.Adapter in its current form doesn't natively 
    // support cursors, we wrap a CursorAdapter that will do all the job
    // for us.
    CursorAdapter mCursorAdapter;

    Context mContext;

    public MyRecyclerAdapter(Context context, Cursor c) {

        mContext = context;

        mCursorAdapter = new CursorAdapter(mContext, c, 0) {

            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                // Inflate the view here
            }

            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                // Binding operations
            }
        };
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        View v1;

        public ViewHolder(View itemView) {
            super(itemView);
            v1 = itemView.findViewById(R.id.v1);
        }
    }

    @Override
    public int getItemCount() {
        return mCursorAdapter.getCount();
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // Passing the binding operation to cursor loader
        mCursorAdapter.getCursor().moveToPosition(position); //EDITED: added this line as suggested in the comments below, thanks :)
        mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // Passing the inflater job to the cursor-adapter
        View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
        return new ViewHolder(v);
    }
}

SimpleCursorAdapter参数之谜

简书作者:zzh0838,原文链接:http://www.jianshu.com/p/daadc9d2bf1a

Question

SimpleCursorAdapter的构造函数是

SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags);

最后一个参数可选的值有:

  • FLAG_AUTO_REQUERY (这个值在Api 11 以后(包含)被弃用了,不用管)
  • FLAG_REGISTER_CONTENT_OBSERVER
  • 0

那到底应该选哪一个呢(虽然只是二选一)?没错,我懵逼了。这个时候,当然是google来帮忙,stackOverFlow搜一搜,but,but,but,搜到的内容都很简略,没人告诉我,我在写SimpleCursorAdapter的时候应该传哪一个参数。

Answer

自己看源码喽,先看看继承继承关系吧(来至官方文档):

java.lang.Object
   ↳    android.widget.BaseAdapter
        ↳    android.widget.CursorAdapter
             ↳    android.widget.ResourceCursorAdapter
                  ↳    android.widget.SimpleCursorAdapter

好吧,先看看SimpleCursorAdapter的默认构造函数吧

public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from,
            int[] to, int flags) {
        super(context, layout, c, flags);
        mTo = to;
        mOriginalFrom = from;
        findColumns(c, from);
    }

可以看到flags传到了父类ResourceCursorAdapter的构造函数。那我们去看看吧。

public ResourceCursorAdapter(Context context, int layout, Cursor c, int flags) {
        super(context, c, flags);
        mLayout = mDropDownLayout = layout;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mDropDownInflater = mInflater;
    }

flags又传到父类CursorAdapter了,再去看看:

public CursorAdapter(Context context, Cursor c, int flags){
        init(context, c, flags);
}

调用了init:

void init(Context context, Cursor c, int flags) {
        if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) {
            flags |= FLAG_REGISTER_CONTENT_OBSERVER;
            mAutoRequery = true;
        } else {
            mAutoRequery = false;
        }
        boolean cursorPresent = c != null;
        mCursor = c;
        mDataValid = cursorPresent;
        mContext = context;
        mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
        if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {
            mChangeObserver = new ChangeObserver();
            mDataSetObserver = new MyDataSetObserver();
        } else {
            mChangeObserver = null;
            mDataSetObserver = null;
        }

        if (cursorPresent) {
            if (mChangeObserver != null) c.registerContentObserver(mChangeObserver);
            if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver);
        }
    }

函数有点长,假设我们的flags设置成了 0,不会有什么操作,假设我们的flags设置成了FLAG_REGISTER_CONTENT_OBSERVER, 那么接下来会构造两个Observer:

mChangeObserver = new ChangeObserver();
mDataSetObserver = new MyDataSetObserver();

并且在cursor不为null的时候将这两个Observer注册给cusor。

if (mChangeObserver != null) c.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver);

那么问题来了,什么时候这两个Observer才会被触发呢?看看Cursor文档吧,文档了这么说的。

当调用方法requery()时,会触发ContentObserver。

当调用方法requery(), deactivate(), or close()时,DataSetObserver会被触发。

然后继续看文档,requery(), deactivate()都被弃用了。调用close后,cursor就没了(Closes the Cursor, releasing all of its resources and making it completely invalid.)。我尼玛,我尼玛,我尼玛,我心里一万只草泥马在奔腾,都不用看两个Observer定义的操作了。传这个参数压根就没什么鸟用。lz彻底懵逼了。

好了,现在可以下结论了:flag永远传0就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值