了解LoaderManager
这篇文章将介绍LoaderManager类,这是该系列的第二篇文章。
一:Loaders之前世界
二:了解LoaderManager
三:实现Loaders
四:实例:AppListLoader

注意:
要了解这一LoaderManager这部分知识,要求对Loaders如何工作有基本了解。Loaders的实现将在下一篇文章中涵盖。现在你只需要将Loaders看成一个简单、字包含的对象。该对象特性包括:1.在一个单独线程载入数据;2.监测底层数据源,当探测到有改变时就更新或者重新查询。了解上面的Loader相关内容就足以了解本文内容了。下文所有的Loaders假设100%正确。

LoaderManager是什么?

简单的理解是,LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象。每个Activity或者Fragment都有唯一的一个LoaderManager实例,用来启动、停止、保持、重启、关闭它的Loaders。这些事件有时直接在客户端通过调用initLoader()/restartLoader()/destroyLoader()函数来实现。通常这些事件通过主要的Activity/Fragment声明周期事件来触发,而不是手动(当然也可以手动调用)。比如,当一个Activity关闭时(destroyed),改活动将指示它的LoaderManager来销毁并且关闭它的Loaders(当然也会销毁并关闭与这些Loaders关联的资源,比如Cursor)。
LoaderManager并不知道数据如何装载以及何时需要装载。相反地,LoaderManager只需要控制它的Loaders们开始、停止、重置他们的Load行为,在配置变换(比如横竖屏切换)时保持loaders们的状态,并提供一个简单的接口来获取load结果到客户端中。从上面的行为可以看到,LoaderManager是一个比现在过时的startManagingCursor方法更加智能和通用的方法。在Activity的声明周期状态轮转中,比较两种管理数据的方法,可以发现LoaderManager方法有下面几个方面更胜一筹:
1. startManagingCursor管理Cursors,而LoaderManager管理Loader<D>对象。Loader<D>是一个模板类,D是一个包含了需要载入数据的类。也就是说,数据源并不必须是Cursor,它可以是List、JSONArray。。。任何类。LoaderManager与它包含的数据内容解耦了,所以更加灵活。
2. 调用startManagingCursor会导致Activity在已经加入管理的Cursor上调用requery()方法。在第一篇文章中提到过,在UI线程执行requery()方法代价非常高。相反的是,Loader<D>的子类会异步载入(译者注:另外再开一个线程,就叫异步了。)数据,所以使用LoaderManager永远不会产生阻塞UI线程的情况。
3. startManagingCursor在配置变化(例如横竖屏切换)时,并不会保持Cursor的状态。麻烦的是,每次Activity由于配置变化(比如,简单的横竖屏切换),都会导致Cursor下回并且被重新查询。LoaderManager就智能多了,当配置变化时,它会保持它里面的Loader们的状态,所以并不需要重新查询数据。
4. LoaderManager提供无缝的数据监测。任何时候,当Loader的数据源改变,LoaderManager将会从对应的Loader上面接收到一个新的同步载入数据,并将更新数据返回给客户端(注意:仅当Loader被正确实现,LoaderManager才会接收到这些数据变化通知。我们将会在该系列的第三篇文章讨论自定义Loaders的实现)。
如果你觉得上面很难,我也并不会强调她。上面的内容最重要的是LoaderManager让你的生活更容易。LoaderManager为你初始化、管理、销毁Loaders,减少了代码复杂度和与Activity或者Fragment生命周期相关的bug。更多地,与LoaderManager交互需要实现三个简单的回调方法,我们在下一节将讨论LoaderManager.LoaderCallbacks<D>。

实现LoaderManager.LoaderCallbacks<D>接口

LoaderManager.LoaderCallbacks<D>接口LoaderManager用来向客户返回数据的方式。每个Loader都有自己的回调对象供与LoaderManager进行交互。该回调对象在实现LoaderManager中地位很高,告诉LoaderManager如何实例化Loader(onCreateLoader),以及当载入行为结束或者重启(onLoadFinished或者onLoadReset)之后执行什么操作。大多数情况,你需要把该接口实现为组件的一部分,比如说让你的Activity或者Fragment实现LoadManager.LoaderCallbacks<D>接口。

public class SampleActivity extends Activity implements LoaderManager.LoaderCallbacks<D> {public Loader<D> onCreateLoader(int id, Bundle args) { ... }public void onLoadFinished(Loader<D> loader, D data) { ... }public void onLoaderReset(Loader<D> loader) { ... }/* ... */
}

一旦实现该接口,客户端将回调对象(本例中为“this”)作为LoaderManager的initLoader函数的第三个参数传输。
总的来说,实现回调接口非常直接明了。每个回调方法都有各自明确的与LoaderManager进行交互的目的:
1. onCreateLoader是一个工厂方法,用来返回一个新的Loader。LoaderManager将会在它第一次创建Loader的时候调用该方法。
2. onLoadFinished方法将在Loader创建完毕的时候自动调用。典型用法是,当载入数据完毕,客户端(译者注:调用它的Activity之类的)需要更新应用UI。客户端假设每次有新数据的时候,新数据都会返回到这个方法中。记住,检测数据源是Loader的工作,Loader也会执行实际的同步载入操作。一旦Loader载入数据完成,LoaderManager将会接受到这些载入数据,并且将将结果传给回调对象的onLoadFinished方法,这样客户端(比如Activity或者Fragment)就能使用该数据了。
3. 最后,当Loader们的数据被重置的时候将会调用onLoadReset。该方法让你可以从就的数据中移除不再有用的数据。
在下一节中,我们将讨论Android初学者们经常问到的问题:如何从过时的Managed Cursor转移到更强大的LoaderManager来?

从Managed Cursor转移到LoaderManager

下面的代码跟上一篇文章的代码实现的功能类似。当然,不同就是改成使用LoaderManager来实现。CursorLoader确保所有的查询都是异步执行,这确保了我们不会阻塞UI线程。更进一步,LoaderManager在Activity全生命周期管理CursorLoader,当配置转换时保持它的数据。处理每次新数据在回调接口的onLoadFinished方法中的载入。这样Activity可以很自由的使用查询结果。

public class SampleListActivity extends ListActivity implementsLoaderManager.LoaderCallbacks<Cursor> {private static final String[] PROJECTION = new String[] { "_id", "text_column" };// The loader's unique id. Loader ids are specific to the Activity or// Fragment in which they reside.private static final int LOADER_ID = 1;// The callbacks through which we will interact with the LoaderManager.private LoaderManager.LoaderCallbacks<Cursor> mCallbacks;// The adapter that binds our data to the ListViewprivate SimpleCursorAdapter mAdapter;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);String[] dataColumns = { "text_column" };int[] viewIDs = { R.id.text_view };// Initialize the adapter. Note that we pass a 'null' Cursor as the// third argument. We will pass the adapter a Cursor only when the// data has finished loading for the first time (i.e. when the// LoaderManager delivers the data to onLoadFinished). Also note// that we have passed the '0' flag as the last argument. This// prevents the adapter from registering a ContentObserver for the// Cursor (the CursorLoader will do this for us!).mAdapter = new SimpleCursorAdapter(this, R.layout.list_item,null, dataColumns, viewIDs, 0);// Associate the (now empty) adapter with the ListView.setListAdapter(mAdapter);// The Activity (which implements the LoaderCallbacks<Cursor>// interface) is the callbacks object through which we will interact// with the LoaderManager. The LoaderManager uses this object to// instantiate the Loader and to notify the client when data is made// available/unavailable.mCallbacks = this;// Initialize the Loader with id '1' and callbacks 'mCallbacks'.// If the loader doesn't already exist, one is created. Otherwise,// the already created Loader is reused. In either case, the// LoaderManager will manage the Loader across the Activity/Fragment// lifecycle, will receive any new loads once they have completed,// and will report this new data back to the 'mCallbacks' object.LoaderManager lm = getLoaderManager();lm.initLoader(LOADER_ID, null, mCallbacks);}@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {// Create a new CursorLoader with the following query parameters.return new CursorLoader(SampleListActivity.this, CONTENT_URI,PROJECTION, null, null, null);}@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {// A switch-case is useful when dealing with multiple Loaders/IDsswitch (loader.getId()) {case LOADER_ID:// The asynchronous load is complete and the data// is now available for use. Only now can we associate// the queried Cursor with the SimpleCursorAdapter.mAdapter.swapCursor(cursor);break;}// The listview now displays the queried data.}@Overridepublic void onLoaderReset(Loader<Cursor> loader) {// For whatever reason, the Loader's data is now unavailable.// Remove any references to the old data by replacing it with// a null Cursor.mAdapter.swapCursor(null);}
}

总结

正如其名LoaderManager,它负责在Activity或者Fragment的生命周期内管理Loader们。LoaderManager很简单,并且它的实现代码量通常很少。比较难的部分是实现Loaders,这个主题将在下一篇文章中讨论:实现Loaders(三)

转载于:https://www.cnblogs.com/android-blogs/p/4962508.html

LoaderManager使用详解(二)---了解LoaderManager相关推荐

  1. Android Loader 异步加载详解二:探寻Loader内部机制

    Android Loader 异步加载详解二:探寻Loader内部机制 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/7025991 ...

  2. 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  3. [转]文件IO详解(二)---文件描述符(fd)和inode号的关系

    原文:https://www.cnblogs.com/frank-yxs/p/5925563.html 文件IO详解(二)---文件描述符(fd)和inode号的关系 ---------------- ...

  4. PopUpWindow使用详解(二)——进阶及答疑

    相关文章: 1.<PopUpWindow使用详解(一)--基本使用> 2.<PopUpWindow使用详解(二)--进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...

  5. Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  6. linux 进程间通信 dbus-glib【实例】详解二(下) 消息和消息总线(ListActivatableNames和服务器的自动启动)(附代码)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  7. linux 进程间通信 dbus-glib【实例】详解二(上) 消息和消息总线(附代码)

    linux 进程间通信 dbus-glib[实例]详解一(附代码)(d-feet工具使用) linux 进程间通信 dbus-glib[实例]详解二(上) 消息和消息总线(附代码) linux 进程间 ...

  8. Android Gradle 自定义Task详解二:进阶

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78523958 本文出自[赵彦军的博客] 系列目录 Android Gradle使用 ...

  9. EXT核心API详解(二)-Array/Date/Function/Number/String

    EXT核心API详解(二)-Array/Date/Function/Number/String Array类 indexOf( Object o )  Number object是否在数组中,找不到返 ...

  10. OS--进程间通信详解(二)

    OS–进程间通信详解(二) 文章目录 OS--进程间通信详解(二) 一.进程间通信 1.互斥量 Futexes Pthreads中的互斥量 2.管程 3.消息传递 消息传递系统的设计要点 用消息传递解 ...

最新文章

  1. .net core i上 K8S(二)运行简单.netcore程序
  2. 阿里云亮相2019联通合作伙伴大会,边缘计算等3款云产品助力5G时代产业数字化转型...
  3. Java虚拟机学习(5):内存调优
  4. PHP5魔术函数与魔术常量
  5. 【269】蓝牙键盘连接
  6. WinForm部署问题
  7. javascript 懒加载技术(lazyload)简单实现
  8. 算法与数据结构 第2章 排序基础 下 插入排序
  9. Unity3d 2019室内光照贴图lightmap快速烘焙(转载)
  10. windows 7 多国语言包官方下载资源共享(32/64位)
  11. 锡兰1.1.0现已上市
  12. 小程序封装请求工具http.js
  13. SAP开发入门-ABAP
  14. 【OVS2.5.0源码分析】sFlow实现分析(3)
  15. 微信公众号文章如何排版?
  16. 数字IC设计 - 逻辑综合简介与Design Compiler使用(GUI方式)
  17. Ubuntu卡在登陆界面循环
  18. Ubuntu中文乱码的解决方案
  19. php短信炸弹,php发送短信炸弹
  20. App/H5/小程序测试技术

热门文章

  1. 中小企业CRM评测-八百客
  2. TCP三次握手的原理及***手段
  3. Flink SQL Client注册SCALA UDF完整流程
  4. Kaggle竞赛方案分享:如何分辨杂草和植物幼苗(转)
  5. git lfs的安装和使用详细案例
  6. DataFrame纵向合并
  7. RHEL7恢复.bashrc文件
  8. 列举mysql的所有触发器以及删除触发器
  9. Clion this file does not belong to any project target问题解决方案
  10. java file类复制文件路径_java进阶(34)--File类、目录复制