使用CursorLoader及更新RecyclerView

  RecyclerView目前还处在“heavy development”的阶段,一些功能仍有待完善。例如ListView可以使用CursorAdapter和CursorLoader,很方便地从ContentProvider获取并更新数据,而RecyclerView并不提供类似CursorAdapter的功能。下面的例子通过从系统通讯录中读取并显示联系人信息,展示了使用CursorLoader更新RecyclerView的方法,其实非常简单,只需在CursorLoader获取到Cursor后,将Cursor更新到Adapter即可。

1. 相关布局

  使用RecyclerView显示联系人列表:

完整文件在这里

  RecyclerView中的item布局如下:

里面只有一个TextView。完整文件在这里

2. 实现swapCursor()

  CursorAdapter提供 swapCursor() 方法来更新Cursor,我们需要在RecyclerView的Adapter中提供自己的实现:

这里 ContactAdapter 使用 mCursor 作为数据集, swapCursor() 方法将传入的 newCursor 更新到本地,并由 notifyDataSetChanged() 通知数据更新。

  完整文件在这里

3. 使用CursorLoader

  使用CursorLoader只需实现 LoaderManager.LoaderCallbacks<Cursor> 接口,重写 onCreateLoader() 、 onLoadFinished() 和 onLoaderReset() 方法。首先要记得在AndroidManifest.xml中声明READ_CONTACTS权限:

3.1. onCreateLoader()

  onCreateLoader()用于生成请求URI并创建CursorLoader:

使用 ContactsContract.Contacts.CONTENT_URI 来获取联系人数据,构造 select 参数选择有实际名字和电话的联系人,由此创建CursorLoader,返回结果按姓名的升序排列。

  注意这里 CONTACTS_SUMMARY_PROJECTION 以数组的形式保存了所需的数据列,并通过int常量保存对应索引:

由此可以很方便的从Cursor中读取各列数据,如获取姓名,只需:

而不必再根据列名获取列的索引,再由索引从Cursor中读取数据。

3.2. onLoadFinished()

  数据获取完成后, onLoadFinished() 会被调用。我们已经在ContactAdapter中实现了 swapCursor() 方法,这里就可以像CursorLoader那样来使用了。

通过 swapCursor() 将获取到的数据 data 送入ContactAdapter,ContactAdapter会进一步地通知数据更新。

3.3. onLoaderReset()

   onLoaderReset() 在之前所创建的CursorLoader被重置时调用,此时之前获取的数据已经无效了,类似CursorLoader,使用 swapCursor() 传入null将Adapter中的数据无效化:

  完整文件在这里

4. 启动CursorLoader

  使用 getLoaderManager().initLoader() 启动CursorLoader, 使用 getLoaderManager().restartLoader() 可以重启CursorLoader。

  完整文件在这里