Android应用Loaders全面详解及源码浅析

来源:互联网 发布:大连共创软件怎么样 编辑:程序博客网 时间:2024/05/17 03:45

1 背景

在Android中任何耗时的操作都不能放在UI主线程中,所以耗时的操作都需要使用异步实现。同样的,在ContentProvider中也可能存在耗时操作,这时也该使用异步操作,而3.0之后最推荐的异步操作就是Loader。它可以方便我们在Activity和Fragment中异步加载数据,而不是用线程或AsyncTask,他的优点如下:

  • 提供异步加载数据机制;
  • 对数据源变化进行监听,实时更新数据;
  • 在Activity配置发生变化(如横竖屏切换)时不用重复加载数据;
  • 适用于任何Activity和Fragment;

PS:由于在我们现在的多个项目中都大量的使用了Loader来处理数据加载(而且由于粗心跳过几个坑,譬如Loader ID重复导致数据逻辑异常、多线程中restartLoader导致Loader抛出异常(最后保证都在UI线程中执行即可)等),所以接下来我们进行下使用及源码浅析。

【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】

PPPS:前方高能,文章巨长,请做好心理准备(您可以选择通过左上角目录点击索引到感兴趣的章节直接查看,或者,或者,或者直接高能往下看)。

2 基础使用实例

该基础实例讲解完全来自于官方文档,详细可以点击我查看英文原文。

既然接下来准备要说说他的使用强大之处了,那不妨我们先来一张图直观的感性认识下不用Loader(左)与用Loader(右)对我们开发者及代码复杂度和框架的影响吧,如下:

这里写图片描述

2-1 Loader API概述说明

如下是我们开发中常用的一些Loader相关接口:

Class/InterfaceDescriptionLoaderManager一个与Activity、Fragment关联的抽象类,用于管理一个或多个Loader实例。每个Activity或Fragment只能有一个LoaderManager,而一个LoaderManager可以有多个Loader。LoaderManager.LoaderCallbacks用于和LoaderManager交互的回调接口。譬如,可以使用onCreateLoader()创建一个新的Loader。AsyncTaskLoader抽象的Loader,提供一个AsyncTask继承实现。CursorLoaderAsyncTaskLoader的子类,用于向ContentResover请求返回一个Cursor。该类以标准游标查询实现了Loader协议,使用后台线程进行查询,使用这个Loader是从ContentProvider加载异步数据最好的方式。

2-2 在应用中使用Loader

在我们开发的一个App里,使用Loader时常规的步骤包含如下一些操作需求:

  • 一个Activity或Fragment;
  • 一个LoaderManager实例;
  • 一个CursorLoader,从ContentProvider加载数据;
  • 一个LoaderManager.LoaderCallbacks实现,创建新Loader及管理已存在Loader;
  • 一个组织Loader数据的Adapter,如SimpleCursorAdapter;

下面我们看下具体流程。

2-2-1 启动一个Loader(initLoader)

一个Activity或Fragment中LoaderManager管理一个或多个Loader实例,每个Activity或Fragment只有一个LoaderManager,我们可以在Activity的onCreate()或Fragment的onActivityCreated()里初始化一个Loader。例如:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Prepare the loader.  Either re-connect with an existing one,</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// or start a new one.</span>getLoaderManager().initLoader(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

可以看见上面的initLoader()方法有三个参数:

  • 第一个参数代表当前Loader的ID;
  • 第二个参数代表提供给Loader构造函数的参数,可选;
  • 第三个参数代表LoaderManager.LoaderCallbacks的回调实现;

上面initLoader()方法的调用确保了一个Loader被初始化和激活的状态,该方法的调运有如下两种结果:

  • 如果代表该Loader的ID已经存在,则后面创建的Loader将直接复用已经存在的;
  • 如果代表该Loader的ID不存在,initLoader()会触发LoaderManager.LoaderCallbacks回调的onCreateLoader()方法创建一个Loader;

可以看见通过initLoader()方法可以将LoaderManager.LoaderCallbacks实例与Loader进行关联,且当Loader的状态变化时就被回调。所以说,如果调用者正处于其开始状态并且被请求的Loader已经存在,且已产生了数据,那么系统会立即调用onLoadFinished()(在initLoader()调用期间),所以你必须考虑到这种情况的发生。

当然了,intiLoader()会返回一个创建的Loader,但是你不用获取它的引用,因为LoadeManager会自动管理该Loader的生命周期,你只用在它回调提供的生命周期方法中做自己数据逻辑的处理即可。

2-2-2 重启一个Loader(restartLoader)

通过上面initLoader()方法介绍我们可以知道initLoader调运后要么得到一个ID已存在的Loader,要么创建一个新的Loader;但是有时我们想丢弃旧数据然后重新开始创建一个新Loader,这可怎么办呢?别担心,要丢弃旧数据调用restartLoader()即可。例如,SearchView.OnQueryTextListener的实现重启了Loader,当用户查询发生变化时Loader需要重启,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onQueryTextChanged</span>(String newText) {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Called when the action bar search text has changed.  Update</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// the search filter, and restart the loader to do a new query</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// with this filter.</span>    mCurFilter = !TextUtils.isEmpty(newText) ? newText : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    getLoaderManager().restartLoader(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

上面方法的参数啥的和再上面的init方法类似,就不再罗嗦了。

2-2-3 使用LoaderManager Callbacks

LoaderManager.LoaderCallbacks是LoaderManager的回调交互接口。LoaderManager.LoaderCallbacks包含如下三个方法:

  • onCreateLoader() 
    实例化并返回一个新创建给定ID的Loader对象;
  • onLoadFinished() 
    当创建好的Loader完成了数据的load之后回调此方法;
  • onLoaderReset() 
    当创建好的Loader被reset时调用此方法,这样保证它的数据无效;

2-2-3-1 onCreateLoader说明

当你尝试使用一个Loader(譬如通过initLoader()方法),它会检查给定Loader的ID是否存在,如果不存在就触发LoaderManager.LoaderCallbacks里的onCreateLoader()方法创建一个新Loader。创建新Loader实例典型的做法就是通过CursorLoader类创建,不过你也可以自定义一个继承自Loader的子类来实现自己的Loader。

下面的例子中我们通过onCreateLoader()回调创建一个CursorLoader实例,使用CursorLoader的构造方法创建实例时需要一些参数去查询一个ContentProvider。具体参数如下:

  • uri 
    准备获取内容的URI。
  • projection 
    要返回的列key list,null表示返回所有列,但是返回所有列很多时候会降低性能;
  • selection 
    要返回的行过滤,也就是SQL中的WHERE语句,null代表返回uri指定的所有行;
  • selectionArgs 
    用来替换上面selection中包含的“?”;
  • sortOrder 
    结果的行排序,也就是SQL中的ORDER BY,传递null则无序;
<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If non-null, this is the current filter the user has provided.</span>String mCurFilter;...<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Loader<Cursor> <span class="hljs-title" style="box-sizing: border-box;">onCreateLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args) {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is called when a new Loader needs to be created.  This</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// sample only has one Loader, so we don't care about the ID.</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// First, pick the base URI to use depending on whether we are</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// currently filtering.</span>    Uri baseUri;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCurFilter != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,                  Uri.encode(mCurFilter));    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {        baseUri = Contacts.CONTENT_URI;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Now create and return a CursorLoader that will take care of</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// creating a Cursor for the data being displayed.</span>    String select = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(("</span> + Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" NOTNULL) AND ("</span>            + Contacts.HAS_PHONE_NUMBER + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=1) AND ("</span>            + Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" != '' ))"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CursorLoader(getActivity(), baseUri,            CONTACTS_SUMMARY_PROJECTION, select, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>,            Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" COLLATE LOCALIZED ASC"</span>);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>

2-2-3-2 onLoadFinished说明

当创建好的Loader完成数据加载时回调此方法,我们要确保该方法在Loader释放现有维持的数据之前被调用。在这里我们应该移除所有对旧数据的使用(因为旧数据不久就会被释放),但是不用释放旧数据,因为Loader会帮我们完成旧数据的释放。

Loader一旦知道App不再使用旧数据就会释放掉。例如,如果数据来自CursorLoader里的一个Cursor,我们不应该自己在代码中调用close()方法;如果一个Cursor正在被放置到一个CursorAdapter时我们应当使用swapCursor()进行新数据交换,这样正在被放置的旧的Cursor就不会被关掉,也就不会导致Adapter的加载异常。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is the Adapter being used to display the list's data.</span>SimpleCursorAdapter mAdapter;...<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadFinished</span>(Loader<Cursor> loader, Cursor data) {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swap the new cursor in.  (The framework will take care of closing the</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// old cursor once we return.)</span>    mAdapter.swapCursor(data);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

2-2-3-3 onLoaderReset说明

当实例化好的Loader被重启时该方法被回调,这里会让Loader的数据置于无效状态。这个回调方法其实就是为了告诉我们啥时候数据要被释放掉,所以我们应该在这个时候移除对它的引用。如下移除实例:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is the Adapter being used to display the list's data.</span>SimpleCursorAdapter mAdapter;...<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoaderReset</span>(Loader<Cursor> loader) {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is called when the last Cursor provided to onLoadFinished()</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// above is about to be closed.  We need to make sure we are no</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// longer using it.</span>    mAdapter.swapCursor(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

2-2-4 Loader使用实例实战

下面这个实例是一个Fragment,模拟的是用ListView显示通讯录的实时匹配查询结果,使用CursorLoader管理通讯录Provider查询。如下源码,比较简单,注释也很丰富了,所以不过多解释:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CursorLoaderListFragment</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ListFragment</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnQueryTextListener</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderManager</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderCallbacks</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Cursor</span>> {</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is the Adapter being used to display the list's data.</span>    SimpleCursorAdapter mAdapter;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If non-null, this is the current filter the user has provided.</span>    String mCurFilter;    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onActivityCreated</span>(Bundle savedInstanceState) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onActivityCreated(savedInstanceState);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Give some text to display if there is no data.  In a real</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// application this would come from a resource.</span>        setEmptyText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No phone numbers"</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We have a menu item to show in action bar.</span>        setHasOptionsMenu(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Create an empty adapter we will use to display the loaded data.</span>        mAdapter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SimpleCursorAdapter(getActivity(),                android.R.layout.simple_list_item_2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>,                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] { android.R.id.text1, android.R.id.text2 }, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);        setListAdapter(mAdapter);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Prepare the loader.  Either re-connect with an existing one,</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// or start a new one.</span>        getLoaderManager().initLoader(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreateOptionsMenu</span>(Menu menu, MenuInflater inflater) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Place an action bar item for searching.</span>        MenuItem item = menu.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Search"</span>);        item.setIcon(android.R.drawable.ic_menu_search);        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);        SearchView sv = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SearchView(getActivity());        sv.setOnQueryTextListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        item.setActionView(sv);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onQueryTextChange</span>(String newText) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Called when the action bar search text has changed.  Update</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// the search filter, and restart the loader to do a new query</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// with this filter.</span>        mCurFilter = !TextUtils.isEmpty(newText) ? newText : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;        getLoaderManager().restartLoader(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onQueryTextSubmit</span>(String query) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Don't care about this.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onListItemClick</span>(ListView l, View v, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> id) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Insert desired behavior here.</span>        Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"FragmentComplexList"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Item clicked: "</span> + id);    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// These are the Contacts rows that we will retrieve.</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String[] CONTACTS_SUMMARY_PROJECTION = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String[] {        Contacts._ID,        Contacts.DISPLAY_NAME,        Contacts.CONTACT_STATUS,        Contacts.CONTACT_PRESENCE,        Contacts.PHOTO_ID,        Contacts.LOOKUP_KEY,    };    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Loader<Cursor> <span class="hljs-title" style="box-sizing: border-box;">onCreateLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is called when a new Loader needs to be created.  This</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// sample only has one Loader, so we don't care about the ID.</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// First, pick the base URI to use depending on whether we are</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// currently filtering.</span>        Uri baseUri;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCurFilter != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,                    Uri.encode(mCurFilter));        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            baseUri = Contacts.CONTENT_URI;        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Now create and return a CursorLoader that will take care of</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// creating a Cursor for the data being displayed.</span>        String select = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(("</span> + Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" NOTNULL) AND ("</span>                + Contacts.HAS_PHONE_NUMBER + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"=1) AND ("</span>                + Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" != '' ))"</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CursorLoader(getActivity(), baseUri,                CONTACTS_SUMMARY_PROJECTION, select, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>,                Contacts.DISPLAY_NAME + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" COLLATE LOCALIZED ASC"</span>);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadFinished</span>(Loader<Cursor> loader, Cursor data) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Swap the new cursor in.  (The framework will take care of closing the</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// old cursor once we return.)</span>        mAdapter.swapCursor(data);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoaderReset</span>(Loader<Cursor> loader) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is called when the last Cursor provided to onLoadFinished()</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// above is about to be closed.  We need to make sure we are no</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// longer using it.</span>        mAdapter.swapCursor(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li></ul>

到此整个Loader基础使用就介绍完了,关于Loader的高级功能,譬如自定义Loader等内容这里先不贴代码说明,因为在这里一下子说完都会觉得蒙圈,而且接受难度也比较大,所以我们在上面这些基础铺垫之后乘热先来源码浅析,有了源码浅析把持住全局结构后再去用Loader的高级用法就会觉得得心应手许多。

【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】

3 源码浅析

和上面的基本使用介绍一样,关于Loader的源码浅析过程会涉及到Activity、Fragment、LoaderManager、Loader、AsyncLoader、CursorLoader等类。所以我们分析的过程还是和以前一样,依据使用顺序进行分析。

我们在分析之前先来看一个Loader框架概要图,如下:

这里写图片描述

通过上面图和前面的基础实例你会发现Loader的框架和各个类的职责都很明确。Activity和Fragment管理LoaderManager,LoaderManager管理Loader,Loader得到数据后触发在LoaderManager中实现的Loader的callback接口,LoaderManager在接收到Loader的callback回传调运时触发我们Activity或Fragment中实现的LoaderManager回调callback接口,就这样就实现了Loader的所有功能,而我们平时写代码一般只用关心LoaderManager的callback实现即可;对于自定义Loader可能还需要关心AsyncTaskLoader子类的实现。

3-1 Activity及Fragment中LoadManager的管理浅析

首先我们都知道,在使用Loader的第一步就是在Activity或者Fragment中获取LoaderManager实例,所以我们先来看下Activity和Fragment是如何管理这些LoaderManager的。

先来看看Fragment中的LoaderManager,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> class FragmentState implements Parcelable {    ......    LoaderManagerImpl mLoaderManager;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mLoadersStarted;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mCheckedForLoaderManager;    ......    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//fragment中获取LoaderManager办法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> LoaderManager <span class="hljs-title" style="box-sizing: border-box;">getLoaderManager</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可以看见,一个Fragment只有一个LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLoaderManager;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mActivity == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Fragment "</span> + <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" not attached to Activity"</span>);        }        mCheckedForLoaderManager = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//从Activity中获取LoaderManager,传入的mWho为当前Fragment的识别key,然后create传入true表示创建!!!!!!</span>        mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLoaderManager;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStart</span>() {        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mLoadersStarted) {            mLoadersStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mCheckedForLoaderManager) {                mCheckedForLoaderManager = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果还没调运过getLoaderManager,那就尝试获取LoaderManager,传入的create为false!!!!!</span>                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);            }            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                mLoaderManager.doStart();            }        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onDestroy</span>() {        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mCheckedForLoaderManager) {            mCheckedForLoaderManager = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果还没调运过getLoaderManager,那就尝试获取LoaderManager,传入的create为false!!!!!</span>            mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mLoaderManager.doDestroy();        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performStart() {        ......        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        onStart();        ......        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mLoaderManager.doReportStart();        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performStop() {        ......        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        onStop();        ......        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoadersStarted) {            mLoadersStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mCheckedForLoaderManager) {                mCheckedForLoaderManager = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果还没调运过getLoaderManager,那就尝试获取LoaderManager,传入的create为false!!!!!</span>                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mActivity == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || !mActivity.mChangingConfigurations) {                    mLoaderManager.doStop();                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                    mLoaderManager.doRetain();                }            }        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performDestroyView() {        ......        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        onDestroyView();        ......        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mLoaderManager.doReportNextStart();        }    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li></ul>

从上面可以看出,Fragment在其生命周期内会控制LoaderManager(LoaderManager其实控制了Loader)的doStart、doDestroy等方法,也就是说我们在Fragment中只管通过getLoaderManager方法来获取LoaderManager实例,然后使用就行,别的Fragment都会帮我们处理OK的。

接下来看看Activity中的LoaderManager,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ContextThemeWrapper</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> ... {</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//mAllLoaderManagers保存了Activity与Fragment的所有LoaderManager</span>    ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;    LoaderManagerImpl mLoaderManager;    ......    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Activity中获取LoaderManager实例的方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> LoaderManager <span class="hljs-title" style="box-sizing: border-box;">getLoaderManager</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可以看见,一个Activity只有一个LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLoaderManager;        }        mCheckedForLoaderManager = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//咦?这不就是上面Fragment的getLoaderManager中调运的那个activity中的getLoaderManager吗,只是和这里的参数不一样而已</span>        mLoaderManager = getLoaderManager(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(root)"</span>, mLoadersStarted, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLoaderManager;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Activity与Fragment获取LoaderManager实例的真正方法!!</span>    LoaderManagerImpl getLoaderManager(String who, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> started, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> create) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//可见一个Activity维护一个mAllLoaderManagers的MAP</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mAllLoaderManagers == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mAllLoaderManagers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayMap<String, LoaderManagerImpl>();        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//尝试从缓存mAllLoaderManagers的MAP中获取已经实例化的LoaderManager实例</span>        LoaderManagerImpl lm = mAllLoaderManagers.get(who);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (lm == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (create) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果没有找到并且需要实例化create(切记这个create参数是很重要的),就调运LoaderManagerImpl构造方法实例化一个LoaderManager对象,然后存入缓存mAllLoaderManagers的MAP中</span>                lm = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LoaderManagerImpl(who, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, started);                mAllLoaderManagers.put(who, lm);            }        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            lm.updateActivity(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> lm;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> invalidateFragment(String who) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mAllLoaderManagers != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            LoaderManagerImpl lm = mAllLoaderManagers.get(who);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (lm != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && !lm.mRetaining) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>                lm.doDestroy();                mAllLoaderManagers.remove(who);            }        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performStop() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoadersStarted) {            mLoadersStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//mChangingConfigurations表示如果当前发生了配置变化则为true,否则为false!!!!!!!重点,Loader特性之一</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mChangingConfigurations) {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当前Activity的stop不是由配置变化引起则直接调用LoaderManager的doStop()方法!!!!!!</span>                    mLoaderManager.doStop();                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当前Activity配置变化,所以需要保存当前的loaderManager,在Activity恢复时恢复这个LoaderManager!!!!!!</span>                    mLoaderManager.doRetain();                }            }        }    ......    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performDestroy() {        ......        onDestroy();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoaderManager != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mLoaderManager.doDestroy();        }        ......    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(@Nullable Bundle savedInstanceState) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLastNonConfigurationInstances != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//从mLastNonConfigurationInstances中恢复mAllLoaderManagers(mLastNonConfigurationInstances是从onAttach中恢复的),Activity配置变化时会走这里!!!!</span>            mAllLoaderManagers = mLastNonConfigurationInstances.loaders;        }        ......        mCalled = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> performStart() {    ......        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mAllLoaderManagers != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> N = mAllLoaderManagers.size();            LoaderManagerImpl loaders[] = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LoaderManagerImpl[N];            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=N-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; i>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i--) {                loaders[i] = mAllLoaderManagers.valueAt(i);            }            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//生命周期依附上LoaderManager</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i<N; i++) {                LoaderManagerImpl lm = loaders[i];                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调用LoaderManager.finishRetain()以及doReportStart()方法来恢复LoaderManager的状态!!!!!</span>                lm.finishRetain();                lm.doReportStart();            }        }        mActivityTransitionState.enterReady(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//该方法会被ActivityThread类调用,且调运时机早于performDestroy()方法!!!!!!</span>    NonConfigurationInstances retainNonConfigurationInstances() {        ......        NonConfigurationInstances nci = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> NonConfigurationInstances();        ......        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//配置变化时保存mAllLoaderManagers!!!!!!</span>        nci.loaders = mAllLoaderManagers;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> nci;    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li></ul>

通过上面的分析可以发现,Activity其实真正的管理了Activity及Fragment的LoaderManager(Fragment也会管理一部分自己LoaderManager的周期),而LoaderManager又管理了Loader,可以发现他们各自的管理范围都是十分的清晰明了的。

3-2 LoadManager及其实现类LoadManagerImpl的浅析

上面分析Activity及Fragment中获取LoaderManager实例时已经知道,我们获取的LoaderManager实例其实就是LoaderManagerImpl对象,而LoaderManagerImpl又是LoaderManager类的子类,所以接下来我们来分析这两个父子类。

先看下抽象父类LoaderManager,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderManager</span> {</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoaderManager的回调接口定义</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderCallbacks</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> {</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">onCreateLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadFinished</span>(Loader<D> loader, D data);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoaderReset</span>(Loader<D> loader);    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//下面这些方法没必要再细说了,上面介绍过的</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">initLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args,            LoaderManager.LoaderCallbacks<D> callback);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">restartLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args,            LoaderManager.LoaderCallbacks<D> callback);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//会触发回调的onLoaderReset方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">destroyLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">getLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">dump</span>(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">enableDebugLogging</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> enabled) {        LoaderManagerImpl.DEBUG = enabled;    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>

可以看见LoaderManager抽象类只是定义了一些规范接口而已,那么接着我们看下抽象类LoaderManager的实现类LoaderManagerImpl,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">class LoaderManagerImpl extends LoaderManager {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LoaderManager"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> DEBUG = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//保存当前存活的Loader</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SparseArray<LoaderInfo> mLoaders = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SparseArray<LoaderInfo>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//保存已经运行完的Loader</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> SparseArray<LoaderInfo> mInactiveLoaders = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SparseArray<LoaderInfo>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String mWho;    Activity mActivity;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mStarted;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mRetaining;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mRetainingStarted;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//是否正在创建Loader,多线程中同时调运创建会导致异常</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mCreatingLoader;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Loader的封装类</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,            Loader.OnLoadCanceledListener<Object> {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mId;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Bundle mArgs;        LoaderManager.LoaderCallbacks<Object> mCallbacks;        Loader<Object> mLoader;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mHaveData;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mDeliveredData;        Object mData;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mStarted;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//mRetaining标记Activity配置变化时保持当前Loader,不用销毁;和上面分析Activity的LoaderManager的retainNonConfigurationInstances方法关联!!!!!!</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mRetaining;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mRetainingStarted;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mReportNextStart;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mDestroyed;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mListenerRegistered;        LoaderInfo mPendingLoader;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoaderInfo构造方法</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">LoaderInfo</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {            mId = id;            mArgs = args;            mCallbacks = callbacks;        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//启动一个Loader</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> start() {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//配置改变恢复则不用启动,用原来的</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mRetaining && mRetainingStarted) {                mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;            }            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果已经启动,则不用再restart了</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mStarted) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;            }            mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果当前封装中mLoader为空并且通过构造方法的mCallbacks不为空则回调onCreateLoader方法创建Loader</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoader == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mCallbacks != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {               mLoader = mCallbacks.onCreateLoader(mId, mArgs);            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoader.getClass().isMemberClass()                        && !Modifier.isStatic(mLoader.getClass().getModifiers())) {                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果当前创建的Loader对象是一个非静态内部类则抛异常!!!!!!</span>                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalArgumentException(                            <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Object returned from onCreateLoader must not be a non-static inner member class: "</span>                            + mLoader);                }                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mListenerRegistered) {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注册Loader的监听方法</span>                    mLoader.registerListener(mId, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);                    mLoader.registerOnLoadCanceledListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);                    mListenerRegistered = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                }                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调运Loader的startLoading方法</span>                mLoader.startLoading();            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Activity的配置改变时进行标志位的设置,以便可以保存,配合上面Activity的分析!!!!!!</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> retain() {            mRetaining = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            ......        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Activity配置变化后重启后如果有数据则通知回调方法,配合上面Activity的分析!!!!!!</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> finishRetain() {            ......            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mStarted && mHaveData && !mReportNextStart) {                callOnLoadFinished(mLoader, mData);            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//配合上面Activity的分析!!!!!!</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> reportStart() {            ......        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//停止Loader</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> stop() {            mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mRetaining) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果不是Activity配置变化,即不用保存则注销掉这些回调</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mListenerRegistered) {                    ......                }            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//取消掉Loader</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> cancel() {            ......        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//销毁掉Loader</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> destroy() {            ......            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCallbacks != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mHaveData && needReset) {                ......                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在destroy时如果有数据存在则调用callback的onLoaderReset方法!!!!!!</span>                    mCallbacks.onLoaderReset(mLoader);                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {                    ......                }            }            ......            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注销监听方法</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mListenerRegistered) {                    ......                }                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//close Cursor等重置操作</span>                mLoader.reset();            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPendingLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                mPendingLoader.destroy();            }        }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Loader被取消时回调该方法</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadCanceled</span>(Loader<Object> loader) {            ......            LoaderInfo pending = mPendingLoader;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//执行最新的Loader</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pending != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                mPendingLoader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;                mLoaders.put(mId, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);                destroy();                installLoader(pending);            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//加载完成时回调</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadComplete</span>(Loader<Object> loader, Object data) {            ......            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//执行最新的Loader</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pending != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                mPendingLoader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;                mLoaders.put(mId, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);                destroy();                installLoader(pending);                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mData != data || !mHaveData) {                mData = data;                mHaveData = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mStarted) {                    callOnLoadFinished(loader, data);                }            }            ......        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调用onLoadFinished</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> callOnLoadFinished(Loader<Object> loader, Object data) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCallbacks != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                ......                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调onLoadFinished方法</span>                    mCallbacks.onLoadFinished(loader, data);                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {                    ......                }                mDeliveredData = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            }        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//!!!!!!真正LoaderManagerImpl的构造方法</span>    LoaderManagerImpl(String who, Activity activity, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> started) {        mWho = who;        mActivity = activity;        mStarted = started;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//更新当前Activity引用</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> updateActivity(Activity activity) {        mActivity = activity;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//私有的创建Loader方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> LoaderInfo <span class="hljs-title" style="box-sizing: border-box;">createLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args,            LoaderManager.LoaderCallbacks<Object> callback) {        LoaderInfo info = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调callback的onCreateLoader方法得到Loader对象</span>        Loader<Object> loader = callback.onCreateLoader(id, args);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把得到的Loader对象包装成LoaderInfo对象</span>        info.mLoader = (Loader<Object>)loader;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> info;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//包装了创建Loader与install方法,并将mCreatingLoader标记置位</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> LoaderInfo <span class="hljs-title" style="box-sizing: border-box;">createAndInstallLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args,            LoaderManager.LoaderCallbacks<Object> callback) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {            mCreatingLoader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调运上面的私有创建方法创建LoaderInfo对象</span>            LoaderInfo info = createLoader(id, args, callback);            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把创建的LoaderInfo对象传入installLoader方法</span>            installLoader(info);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> info;        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {            mCreatingLoader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> installLoader(LoaderInfo info) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将创建的LoaderInfo对象存入mLoaders的Map中</span>        mLoaders.put(info.mId, info);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mStarted) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果Activity已经started,则启动LoaderInfo的start方法</span>            info.start();        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//public的方法,创建一个Loader,前面介绍过的</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@SuppressWarnings</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"unchecked"</span>)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">initLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果多线程中正在有创建的则抛出异常(写代码要注意这种情况,尤其是跑Monkey容易抛出,解决办法就是保证都在统一线程中执行!!!!!!)</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCreatingLoader) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Called while creating a loader"</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//从现有的Map中尝试获取指定ID的LoaderInfo对象</span>        LoaderInfo info = mLoaders.get(id);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//发现不存在就调运上面的createAndInstallLoader创建一个</span>            info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//否则还用当前的Loader,只是重新赋值了callBack而已</span>            info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.mHaveData && mStarted) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//已经有数据,直接调运LoaderInfo的callOnLoadFinished</span>            info.callOnLoadFinished(info.mLoader, info.mData);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//返回Loader对象</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (Loader<D>)info.mLoader;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新创造Loader,前面介绍过的</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@SuppressWarnings</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"unchecked"</span>)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">restartLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCreatingLoader) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果多线程中正在有创建的则抛出异常(写代码要注意这种情况,尤其是跑Monkey容易抛出,解决办法就是保证都在统一线程中执行!!!!!!)</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Called while creating a loader"</span>);        }        LoaderInfo info = mLoaders.get(id);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            LoaderInfo inactive = mInactiveLoaders.get(id);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (inactive != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.mHaveData) {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//发现是已经运行完的Loader且已经存在的Loader有数据则destroy掉运行完的Loader</span>                    inactive.mDeliveredData = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;                    inactive.destroy();                    info.mLoader.abandon();                    mInactiveLoaders.put(id, info);                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!info.mStarted) {                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//有相同id的Loader还没start则destory掉</span>                        mLoaders.put(id, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);                        info.destroy();                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//有一个相同id的Loader正在加载数据,但是还没加载完,调用它的cancel()方法通知取消加载</span>                        info.cancel();                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.mPendingLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                            info.mPendingLoader.destroy();                            info.mPendingLoader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;                        }                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建一个指定id的Loader同时赋给mPendingLoader,因为这个时候已经有一个Loader正在加载数据,而且我们已经调用了其cancel()方法来通知取消加载</span>                        info.mPendingLoader = createLoader(id, args,                                 (LoaderManager.LoaderCallbacks<Object>)callback);                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//返回创建的Loader</span>                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (Loader<D>)info.mPendingLoader.mLoader;                    }                }            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//终止已存在的Loader</span>                info.mLoader.abandon();                mInactiveLoaders.put(id, info);            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新创建Loader返回</span>        info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (Loader<D>)info.mLoader;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//销毁指定id的Loader</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">destroyLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCreatingLoader) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Called while creating a loader"</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不解释,单纯的destory</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> idx = mLoaders.indexOfKey(id);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (idx >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {            LoaderInfo info = mLoaders.valueAt(idx);            mLoaders.removeAt(idx);            info.destroy();        }        idx = mInactiveLoaders.indexOfKey(id);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (idx >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {            LoaderInfo info = mInactiveLoaders.valueAt(idx);            mInactiveLoaders.removeAt(idx);            info.destroy();        }        ......    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取指定id的Loader对象</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@SuppressWarnings</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"unchecked"</span>)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <D> Loader<D> <span class="hljs-title" style="box-sizing: border-box;">getLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCreatingLoader) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IllegalStateException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Called while creating a loader"</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//优先获取LoaderInfo中的mPendingLoader</span>        LoaderInfo loaderInfo = mLoaders.get(id);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (loaderInfo != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (loaderInfo.mPendingLoader != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (Loader<D>)loaderInfo.mPendingLoader.mLoader;            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (Loader<D>)loaderInfo.mLoader;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    }    ......}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li><li style="box-sizing: border-box; padding: 0px 5px;">240</li><li style="box-sizing: border-box; padding: 0px 5px;">241</li><li style="box-sizing: border-box; padding: 0px 5px;">242</li><li style="box-sizing: border-box; padding: 0px 5px;">243</li><li style="box-sizing: border-box; padding: 0px 5px;">244</li><li style="box-sizing: border-box; padding: 0px 5px;">245</li><li style="box-sizing: border-box; padding: 0px 5px;">246</li><li style="box-sizing: border-box; padding: 0px 5px;">247</li><li style="box-sizing: border-box; padding: 0px 5px;">248</li><li style="box-sizing: border-box; padding: 0px 5px;">249</li><li style="box-sizing: border-box; padding: 0px 5px;">250</li><li style="box-sizing: border-box; padding: 0px 5px;">251</li><li style="box-sizing: border-box; padding: 0px 5px;">252</li><li style="box-sizing: border-box; padding: 0px 5px;">253</li><li style="box-sizing: border-box; padding: 0px 5px;">254</li><li style="box-sizing: border-box; padding: 0px 5px;">255</li><li style="box-sizing: border-box; padding: 0px 5px;">256</li><li style="box-sizing: border-box; padding: 0px 5px;">257</li><li style="box-sizing: border-box; padding: 0px 5px;">258</li><li style="box-sizing: border-box; padding: 0px 5px;">259</li><li style="box-sizing: border-box; padding: 0px 5px;">260</li><li style="box-sizing: border-box; padding: 0px 5px;">261</li><li style="box-sizing: border-box; padding: 0px 5px;">262</li><li style="box-sizing: border-box; padding: 0px 5px;">263</li><li style="box-sizing: border-box; padding: 0px 5px;">264</li><li style="box-sizing: border-box; padding: 0px 5px;">265</li><li style="box-sizing: border-box; padding: 0px 5px;">266</li><li style="box-sizing: border-box; padding: 0px 5px;">267</li><li style="box-sizing: border-box; padding: 0px 5px;">268</li><li style="box-sizing: border-box; padding: 0px 5px;">269</li><li style="box-sizing: border-box; padding: 0px 5px;">270</li><li style="box-sizing: border-box; padding: 0px 5px;">271</li><li style="box-sizing: border-box; padding: 0px 5px;">272</li><li style="box-sizing: border-box; padding: 0px 5px;">273</li><li style="box-sizing: border-box; padding: 0px 5px;">274</li><li style="box-sizing: border-box; padding: 0px 5px;">275</li><li style="box-sizing: border-box; padding: 0px 5px;">276</li><li style="box-sizing: border-box; padding: 0px 5px;">277</li><li style="box-sizing: border-box; padding: 0px 5px;">278</li><li style="box-sizing: border-box; padding: 0px 5px;">279</li><li style="box-sizing: border-box; padding: 0px 5px;">280</li><li style="box-sizing: border-box; padding: 0px 5px;">281</li><li style="box-sizing: border-box; padding: 0px 5px;">282</li><li style="box-sizing: border-box; padding: 0px 5px;">283</li><li style="box-sizing: border-box; padding: 0px 5px;">284</li><li style="box-sizing: border-box; padding: 0px 5px;">285</li><li style="box-sizing: border-box; padding: 0px 5px;">286</li><li style="box-sizing: border-box; padding: 0px 5px;">287</li><li style="box-sizing: border-box; padding: 0px 5px;">288</li><li style="box-sizing: border-box; padding: 0px 5px;">289</li><li style="box-sizing: border-box; padding: 0px 5px;">290</li><li style="box-sizing: border-box; padding: 0px 5px;">291</li><li style="box-sizing: border-box; padding: 0px 5px;">292</li><li style="box-sizing: border-box; padding: 0px 5px;">293</li><li style="box-sizing: border-box; padding: 0px 5px;">294</li><li style="box-sizing: border-box; padding: 0px 5px;">295</li><li style="box-sizing: border-box; padding: 0px 5px;">296</li><li style="box-sizing: border-box; padding: 0px 5px;">297</li><li style="box-sizing: border-box; padding: 0px 5px;">298</li><li style="box-sizing: border-box; padding: 0px 5px;">299</li><li style="box-sizing: border-box; padding: 0px 5px;">300</li><li style="box-sizing: border-box; padding: 0px 5px;">301</li><li style="box-sizing: border-box; padding: 0px 5px;">302</li><li style="box-sizing: border-box; padding: 0px 5px;">303</li><li style="box-sizing: border-box; padding: 0px 5px;">304</li><li style="box-sizing: border-box; padding: 0px 5px;">305</li><li style="box-sizing: border-box; padding: 0px 5px;">306</li><li style="box-sizing: border-box; padding: 0px 5px;">307</li><li style="box-sizing: border-box; padding: 0px 5px;">308</li><li style="box-sizing: border-box; padding: 0px 5px;">309</li><li style="box-sizing: border-box; padding: 0px 5px;">310</li><li style="box-sizing: border-box; padding: 0px 5px;">311</li><li style="box-sizing: border-box; padding: 0px 5px;">312</li><li style="box-sizing: border-box; padding: 0px 5px;">313</li><li style="box-sizing: border-box; padding: 0px 5px;">314</li><li style="box-sizing: border-box; padding: 0px 5px;">315</li><li style="box-sizing: border-box; padding: 0px 5px;">316</li><li style="box-sizing: border-box; padding: 0px 5px;">317</li><li style="box-sizing: border-box; padding: 0px 5px;">318</li><li style="box-sizing: border-box; padding: 0px 5px;">319</li><li style="box-sizing: border-box; padding: 0px 5px;">320</li><li style="box-sizing: border-box; padding: 0px 5px;">321</li><li style="box-sizing: border-box; padding: 0px 5px;">322</li><li style="box-sizing: border-box; padding: 0px 5px;">323</li><li style="box-sizing: border-box; padding: 0px 5px;">324</li><li style="box-sizing: border-box; padding: 0px 5px;">325</li><li style="box-sizing: border-box; padding: 0px 5px;">326</li><li style="box-sizing: border-box; padding: 0px 5px;">327</li><li style="box-sizing: border-box; padding: 0px 5px;">328</li><li style="box-sizing: border-box; padding: 0px 5px;">329</li><li style="box-sizing: border-box; padding: 0px 5px;">330</li><li style="box-sizing: border-box; padding: 0px 5px;">331</li><li style="box-sizing: border-box; padding: 0px 5px;">332</li><li style="box-sizing: border-box; padding: 0px 5px;">333</li><li style="box-sizing: border-box; padding: 0px 5px;">334</li><li style="box-sizing: border-box; padding: 0px 5px;">335</li><li style="box-sizing: border-box; padding: 0px 5px;">336</li><li style="box-sizing: border-box; padding: 0px 5px;">337</li><li style="box-sizing: border-box; padding: 0px 5px;">338</li><li style="box-sizing: border-box; padding: 0px 5px;">339</li><li style="box-sizing: border-box; padding: 0px 5px;">340</li><li style="box-sizing: border-box; padding: 0px 5px;">341</li><li style="box-sizing: border-box; padding: 0px 5px;">342</li></ul>

我勒个去!好长,好累!通过上面粗略的分析你会发现和我们上面基础实例介绍LoaderManager的方法时描述的一样,每个方法都有自己的特点,发挥着各自的作用,LoaderManager的实质是将Loader对象转换为LoaderInfo来进行管理,也就是管理了所有的Loader对象。

3-3 Loader及其实现类的浅析

上面分析了Activity及Fragment管理了LoaderManager的相关方法,LoaderManager管理了Loader的相关方法,那么接下来我们就来看看这个被管理的终极目标Loader是咋回事,还有他的子类咋回事。

先来看看我画的一张关系图,如下:

这里写图片描述

我去,这图现在看可能有些吓人,我们还是先来慢慢分析一下再说吧。

3-3-1 Loader基类源码浅析

我们先来看看这个Loader基类吧,该类核心方法及内部类结构图如下:

这里写图片描述

代码分析如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Loader</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mId;    OnLoadCompleteListener<D> mListener;    OnLoadCanceledListener<D> mOnLoadCanceledListener;    Context mContext;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mAbandoned = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mReset = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mContentChanged = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mProcessingChange = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//数据源变化监听器(观察者模式),实现了ContentObserver类</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ForceLoadContentObserver</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ContentObserver</span> {</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">ForceLoadContentObserver</span>() {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Handler());        }        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">deliverSelfNotifications</span>() {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        }        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onChange</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> selfChange) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实质是调运Loader的forceLoad方法</span>            onContentChanged();        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Loader加载完成接口,当加载完成时Loader通知loaderManager,loaderManager再回调我们initLoader方法的callback</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnLoadCompleteListener</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> {</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadComplete</span>(Loader<D> loader, D data);    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoaderManager中监听cancel,同上类似</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnLoadCanceledListener</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> {</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadCanceled</span>(Loader<D> loader);    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//构造方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Loader</span>(Context context) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//mContext持有Application的Context,防止泄露内存等</span>        mContext = context.getApplicationContext();    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//加载完成时回调传递加载数据结果,实质是对OnLoadCompleteListener接口方法的封装</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deliverResult</span>(D data) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mListener.onLoadComplete(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, data);        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//类似同上,对OnLoadCanceledListener的方法的封装</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deliverCancellation</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mOnLoadCanceledListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mOnLoadCanceledListener.onLoadCanceled(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Context <span class="hljs-title" style="box-sizing: border-box;">getContext</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mContext;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getId</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mId;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">registerListener</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, OnLoadCompleteListener<D> listener) {        mListener = listener;        mId = id;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">unregisterListener</span>(OnLoadCompleteListener<D> listener) {        mListener = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">registerOnLoadCanceledListener</span>(OnLoadCanceledListener<D> listener) {        mOnLoadCanceledListener = listener;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">unregisterOnLoadCanceledListener</span>(OnLoadCanceledListener<D> listener) {        mOnLoadCanceledListener = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isStarted</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mStarted;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isAbandoned</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mAbandoned;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isReset</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mReset;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//开始加载数据时LoaderManager会调用该方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">startLoading</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置标记</span>        mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        mReset = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        mAbandoned = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        onStartLoading();    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//真正开始加载数据的地方******空方法,子类实现!!!!!!</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStartLoading</span>() {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//取消Loader的方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">cancelLoad</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> onCancelLoad();    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//真正取消的地方******,子类实现!!!!!!return false表示取消失败(因为已完成或未开始)</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onCancelLoad</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//强制重新Loader,放弃旧数据</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">forceLoad</span>() {        onForceLoad();    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//真正重新Loader的地方******空方法,子类实现!!!!!!</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onForceLoad</span>() {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//同上</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">stopLoading</span>() {        mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        onStopLoading();    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStopLoading</span>() {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//同上</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">abandon</span>() {        mAbandoned = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        onAbandon();    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onAbandon</span>() {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//同上</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">reset</span>() {        onReset();        mReset = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        mStarted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        mAbandoned = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        mContentChanged = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        mProcessingChange = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onReset</span>() {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Loader数据变化的一些标记处理</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">takeContentChanged</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> res = mContentChanged;        mContentChanged = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;        mProcessingChange |= res;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> res;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">commitContentChanged</span>() {        mProcessingChange = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">rollbackContentChanged</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mProcessingChange) {            mContentChanged = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//上面ForceLoadContentObserver内部类的onChange方法调运</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onContentChanged</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mStarted) {            forceLoad();        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            mContentChanged = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//一些方便调试的方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">dataToString</span>(D data)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">toString</span>()    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">dump</span>(String prefix, FileDescriptor fd, PrintWriter writer, String[] args)}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li></ul>

通过上面粗略的分析可以发现,Loader基类无非也就是一个方法接口的定义类,组织预留了一些方法供LoaderManager去调运处理,同时需要子类实现其提供的一些onXXX方法,以便LoaderManager调运Loader的方法时可以触发Loader子类的实现逻辑。

3-3-2 AsyncTaskLoader抽象子类源码浅析

上面既然说了Loader类的作用主要是规定接口,同时供LoaderManager管理,那LoaderManager管理的Loader自然需要做一些事情,也就是说我们需要继承Loader实现一些逻辑操作。然而好在系统API已经帮我们实现了一些简单的封装实现,我们这里就先来看下Loader的直接子类AsyncTaskLoader吧,先来看下该抽象子类的方法及内部类粗略图,如下:

这里写图片描述

代码分析如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AsyncTaskLoader</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Loader</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">D</span>> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AsyncTaskLoader"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> DEBUG = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoadTask内部类是对AsyncTask的封装,实现了Runnable接口</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {        ......        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> D <span class="hljs-title" style="box-sizing: border-box;">doInBackground</span>(Void... params) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//AsyncTask的子线程中执行AsyncTaskLoader的onLoadInBackground方法!!!!重点</span>                D data = AsyncTaskLoader.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.onLoadInBackground();                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把执行结果数据D返回到UI线程</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> data;            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (OperationCanceledException ex) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!isCancelled()) {                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> ex;                }                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;            }        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* Runs on the UI thread */</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPostExecute</span>(D data) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//AsyncTask子线程执行完毕后回调AsyncTaskLoader的dispatchOnLoadComplete方法</span>            AsyncTaskLoader.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.dispatchOnLoadComplete(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, data);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* Runs on the UI thread */</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCancelled</span>(D data) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//取消AsyncTask时调运</span>            AsyncTaskLoader.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.dispatchOnCancelled(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, data);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Runnable的实现方法</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {            waiting = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;            AsyncTaskLoader.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.executePendingTask();        }    ......    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Executor mExecutor;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> LoadTask mTask;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> LoadTask mCancellingTask;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> mUpdateThrottle;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> mLastLoadCompleteTime = -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10000</span>;    Handler mHandler;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//public构造方法</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AsyncTaskLoader</span>(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(context, AsyncTask.THREAD_POOL_EXECUTOR);    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** {@hide} 无法被外部调运的构造方法 */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AsyncTaskLoader</span>(Context context, Executor executor) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);        mExecutor = executor;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setUpdateThrottle</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> delayMS) {        mUpdateThrottle = delayMS;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (delayMS != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {            mHandler = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Handler();        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onForceLoad</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onForceLoad();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//取消当前的Loader</span>        cancelLoad();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//新建task并执行</span>        mTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LoadTask();        executePendingTask();    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onCancelLoad</span>() {        ......    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCanceled</span>(D data) {    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoadTask的Runnable方法run中执行</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> executePendingTask() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCancellingTask == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mTask != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mTask.waiting) {                mTask.waiting = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;                mHandler.removeCallbacks(mTask);            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mUpdateThrottle > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> now = SystemClock.uptimeMillis();                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (now < (mLastLoadCompleteTime+mUpdateThrottle)) {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Not yet time to do another load.</span>                    mTask.waiting = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                    mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;                }            }            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//真正的触发执行AsyncTask方法</span>            mTask.executeOnExecutor(mExecutor, (Void[]) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> dispatchOnCancelled(LoadTask task, D data) {        onCanceled(data);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCancellingTask == task) {            rollbackContentChanged();            mLastLoadCompleteTime = SystemClock.uptimeMillis();            mCancellingTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//触发Loader的接口方法onLoadCanceled,在LoaderManager中实现</span>            deliverCancellation();            executePendingTask();        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> dispatchOnLoadComplete(LoadTask task, D data) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mTask != task) {            dispatchOnCancelled(task, data);        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isAbandoned()) {                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This cursor has been abandoned; just cancel the new data.</span>                onCanceled(data);            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                commitContentChanged();                mLastLoadCompleteTime = SystemClock.uptimeMillis();                mTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//触发Loader的接口方法onLoadComplete,在LoaderManager中实现</span>                deliverResult(data);            }        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//需要子类实现!!!!!在子线程中执行</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> D <span class="hljs-title" style="box-sizing: border-box;">loadInBackground</span>();    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoadTask(AsyncTask的子线程中回调)中调运</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> D <span class="hljs-title" style="box-sizing: border-box;">onLoadInBackground</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> loadInBackground();    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//LoadTask(AsyncTask的onCancelLoad中回调)调运</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">cancelLoadInBackground</span>() {    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isLoadInBackgroundCanceled</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mCancellingTask != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//锁标记处理</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">waitForLoader</span>() {        LoadTask task = mTask;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (task != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            task.waitForLoader();        }    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li></ul>

可以看见上面继承Loader的AsyncTaskLoader其实质是提供了一个基于AsyncTask工作机制的Loader(子类LoadTask继承AsyncTask<Void, Void, D>,并且实现了Runable接口,功能十分强大。),但是不可直接用,因为其为abstract抽象类,所以我们需要继承实现它才可以使用,然而好在系统API已经帮我们提供了他现成的子类CursorLoader,但CursorLoader同时也限制了Loader的泛型数据为Cursor类型。当然了,我们如果想要Loader自己的类型数据那也很简单—继承实现AsyncTaskLoader即可,后面会给出例子的。

3-3-3 CursorLoader子类源码浅析

有了上面继承自Loader的抽象AsyncTaskLoader,接下来我们就来看看SDK为我们提供的抽象AsyncTaskLoader实现类CursorLoader,我们先来粗略看看该类的方法图,如下:

这里写图片描述

具体代码分析如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//继承自AsyncTaskLoader,数据类型为Cursor的Loader异步加载实现类</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">CursorLoader</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AsyncTaskLoader</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Cursor</span>> {</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Cursor的子类ForceLoadContentObserver</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ForceLoadContentObserver mObserver;    Uri mUri;    String[] mProjection;    String mSelection;    String[] mSelectionArgs;    String mSortOrder;    Cursor mCursor;    CancellationSignal mCancellationSignal;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* Runs on a worker thread     最核心的实现方法,在这里查询获取数据 */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Cursor <span class="hljs-title" style="box-sizing: border-box;">loadInBackground</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isLoadInBackgroundCanceled()) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OperationCanceledException();            }            mCancellationSignal = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CancellationSignal();        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不过多解释,耗时的查询操作</span>            Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,                    mSelectionArgs, mSortOrder, mCancellationSignal);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (cursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Ensure the cursor window is filled.</span>                    cursor.getCount();                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//给Cursor设置观察者;ContentProvider通知Cursor的观察者数据发生了改变,Cursor通知CursorLoader的观察者数据发生了改变,CursorLoader通过ContentProvider重新加载新的数据</span>                    cursor.registerContentObserver(mObserver);                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (RuntimeException ex) {                    cursor.close();                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> ex;                }            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> cursor;        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span> {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {                mCancellationSignal = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;            }        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">cancelLoadInBackground</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.cancelLoadInBackground();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">synchronized</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCancellationSignal != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                mCancellationSignal.cancel();            }        }    }    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* Runs on the UI thread */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deliverResult</span>(Cursor cursor) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isReset()) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// An async query came in while the loader is stopped</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (cursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                cursor.close();            }            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;        }        Cursor oldCursor = mCursor;        mCursor = cursor;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isStarted()) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.deliverResult(cursor);        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (oldCursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && oldCursor != cursor && !oldCursor.isClosed()) {            oldCursor.close();        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">CursorLoader</span>(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);        mObserver = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ForceLoadContentObserver();    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">CursorLoader</span>(Context context, Uri uri, String[] projection, String selection,            String[] selectionArgs, String sortOrder) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//新建一个当前类(Loader)的内部类对象,数据库变化时调运ForceLoadContentObserver的onChange方法,onChange调运Loader的onContentChanged方法,onContentChanged调运Loader的forceLoad方法</span>        mObserver = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ForceLoadContentObserver();        mUri = uri;        mProjection = projection;        mSelection = selection;        mSelectionArgs = selectionArgs;        mSortOrder = sortOrder;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStartLoading</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            deliverResult(mCursor);        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (takeContentChanged() || mCursor == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            forceLoad();        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStopLoading</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Attempt to cancel the current load task if possible.</span>        cancelLoad();    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCanceled</span>(Cursor cursor) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (cursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && !cursor.isClosed()) {            cursor.close();        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onReset</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onReset();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Ensure the loader is stopped</span>        onStopLoading();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mCursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && !mCursor.isClosed()) {            mCursor.close();        }        mCursor = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Uri <span class="hljs-title" style="box-sizing: border-box;">getUri</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mUri;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setUri</span>(Uri uri) {        mUri = uri;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String[] <span class="hljs-title" style="box-sizing: border-box;">getProjection</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mProjection;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setProjection</span>(String[] projection) {        mProjection = projection;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getSelection</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mSelection;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setSelection</span>(String selection) {        mSelection = selection;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String[] <span class="hljs-title" style="box-sizing: border-box;">getSelectionArgs</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mSelectionArgs;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setSelectionArgs</span>(String[] selectionArgs) {        mSelectionArgs = selectionArgs;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getSortOrder</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mSortOrder;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setSortOrder</span>(String sortOrder) {        mSortOrder = sortOrder;    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li></ul>

可以发现,CursorLoader的封装大大简化了应用开发者代码的复杂度;它完全就是一个异步的数据库查询瑞士军刀,没有啥特别需要分析的地方,所以不再过多说明。

3-4 Loaders相关源码浅析总结

通过上面我们的源码分析和分析前那副图可以总结如下结论:

  • 一次完整的数据加载流程为Activity调用LoaderManager的doStart()方法,然后LoaderManager调用Loader的startLoading()方法,然后Loader调运AsyncTaskLoader的doingBackground()方法进行耗时数据加载,然后AsyncTaskLoader回调LoaderManager的complete数据加载完成方法,接着LoaderManager回调我们在Activity中实现的callback中的onLoadFinish()方法。

  • Acivity和Fragment的生命周期主动管理了LoaderManager,每个Activity用一个ArrayMap的mAllLoaderManager来保存当前Activity及其附属Frament的唯一LoaderManager;在Activity配置发生变化时,Activity在destory前会保存mAllLoaderManager,当Activity再重新创建时,会在Activity的onAttcach()、onCreate()、performStart()方法中恢复mAllLoaderManager。

  • LoaderManager给Activity提供了管理自己的一些方法;同时主动管理了对应的Loader,它把每一个Loader封装为LoadInfo对象,同时它负责主动调运管理Loader的startLoading()、stopLoading()、,forceLoad()等方法。

  • 由于整个Activity和Fragment主动管理了Loader,所以关于Loader的释放(譬如CursorLoader的Cursor关闭等)不需要我们人为处理,Loader框架会帮我们很好的处理的;同时特别注意,对于CursorLoader,当我们数据源发生变化时Loader框架会通过ContentObserver调用onContentChanged的forceLoad方法重新请求数据进行回调刷新。

好了,至此你会发现Loader真的很牛叉,No!应该是Google的工程师真的很牛叉,架构真的很赞,值得推荐。

【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】

4 应用层开发之Loader进阶实战

上面对于Loader的基础使用及源码框架都进行了简单分析,有了上面的铺垫我们再回过头来看看我们开发中的一些高级技巧,通过这些高级技巧不仅是对前面源码分析的实例验证,也是对自己知识的积累。

4-1 ContentPorvider情况下的CurSorLoader自动刷新

在我们使用CurSorLoader时大家都会考虑一种情况的处理—–当数据库发生变化时如何自动刷新当前UI。呵呵,我们先来说说这个原理,数据库在数据改变时通过ContentPorvider和ContentResolver发出通知,接着ContentProvider通知Cursor的观察者数据发生了变化,然后Cursor通知CursorLoader的观察者数据发生了变化,接着CursorLoader通过ContentProvider加载新数据,完事调用CursorAdapter的changeCursor()用新数据替换旧数据显示。

这个过程具体的实现步骤如下:

  1. 对获取的Cursor数据设置需要监听的URI(即,在ContentProvider的query()方法或者Loader的loadingBackground()方法中调用Cursor的setNotificationUri()方法);

  2. 在ContentProvider的insert()、update()、delete()等方法中调用ContentResolver的notifyChange()方法;

通过上面两步我们就能享受CurSorLoader的自动数据刷新功能了;可以发现,所谓的CurSorLoader自动刷新无非就是观察者模式的框架而已,所以不再过多说明。

特别注意:

有些人觉得为了方便可能会将上面第一步对于Cursor设置监听直接写在了ContentProvider的query()方法中,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Cursor <span class="hljs-title" style="box-sizing: border-box;">query</span>(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder) {    SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();    Cursor cursor = database.query(EmailContent.CONTACT_TABLE, projection,    selection,selectionArgs, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, sortOrder);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置NotificationUri监听</span>    cursor.setNotificationUri(contentResolver, EmailContent.MESSAGE);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> cursor;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

这里要提醒的是,这种写法在某些场合下是不值得推荐的(譬如大规模上千次并发平凡的调运query操作场合),因为效率极低,他会频繁的通过Binder进行通信,导致system_server不停的调运GC操作,以至于会使系统卡顿。

PS:因为我以前跳过一次这个坑,平时使用应用没啥问题,但是当进行压力测试时却发现LogCat一直在不停的打印GC,同时导致当前系统卡顿,杀掉应用后系统就不卡了,所以基本怀疑问题就出在了应用中,于是通过很多办法去查找(譬如dempsys content去查看个数),最终发现罪魁祸首是这个监听频繁调运导致的,随将其挪到loadingBackground中不再卡顿。

4-2 不使用ContentPorvider且自定义Loader的情况下自动刷新

我们目前的项目其实都使用了ContentPorvider实现,所以就是上面讲的那些情况。但是你一定会问,如果我们应用的数据不用于应用间共享,使用ContentProvider那得多麻烦啊?我先告诉你,是很麻烦,但是Android提供的CursorLoader的API必须使用ContentProvider才能实现数据加载和自动刷新。

这时候你指定会说,那还说个屁!哎,别急,你看看下面这段代码是否会有所感触呢,如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> NoProviderLoader extends AsyncTaskLoader {    ......    ForceLoadContentObserver mObserver = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ForceLoadContentObserver();    ......    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Cursor <span class="hljs-title" style="box-sizing: border-box;">loadInBackground</span>() {        SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();        Cursor cursor = database.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (cursor != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//最重要的两行代码!!!!!!</span>            cursor.registerContentObserver(mObserver);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//给Cursor设置观察者</span>            cursor.setNotificationUri(getContext().getContentResolver(), otificationUri);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//给Cursor设置要观察的URI</span>        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> cursor;    }    ......}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

咦?是不是上面代码很奇怪,异步操作的方法中没有使用ContentProvider,而是直接读取了数据库。握草!这不就是我们刚刚想要的需求么,它没有使用ContentProvider提供Cursor数据,同时实现了数据变化自动更新功能。

简单解释下上面代码的原理吧,我们自定义的NoProviderLoader中定义的ForceLoadContentObserver是Loader的一个内部类,上面源码分析已经解释过了,当数据变化时会调运该类的onChange()方法,实质是调运了Loader的forceLoad()方法,所以能够自动刷新,不多解释了。

4-3 Loader自定义之AsyncTaskLoader衍生

可能看到这里你更加会举一反三的反驳一句了,上面搞了半天都是和数据库Cursor相关的东东,难道Loader就不能异步处理别的数据结构么?答案是能,因为你可能已经注意到了Loader和AsyncTaskLoader都是泛型类;既然这样,那我们找猫画虎一把呗,仿照CursorLoader自定义一个自己的异步加载试试,具体实现如下(哈哈,想了又想,这里还是直接给出官方的自定义AsyncTaskLoader好点,毕竟权威些,详细点我查看官方自定义实现Demo):

官方对于查询已安装App列表的Loader实现,支持新App安装后自动刷新的功能,实现如下:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * This class holds the per-item data in our Loader. */</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppEntry</span> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AppEntry</span>(AppListLoader loader, ApplicationInfo info) {        mLoader = loader;        mInfo = info;        mApkFile = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(info.sourceDir);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ApplicationInfo <span class="hljs-title" style="box-sizing: border-box;">getApplicationInfo</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mInfo;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getLabel</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLabel;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Drawable <span class="hljs-title" style="box-sizing: border-box;">getIcon</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mIcon == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mApkFile.exists()) {                mIcon = mInfo.loadIcon(mLoader.mPm);                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mIcon;            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                mMounted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;            }        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mMounted) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If the app wasn't mounted but is now mounted, reload</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// its icon.</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mApkFile.exists()) {                mMounted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                mIcon = mInfo.loadIcon(mLoader.mPm);                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mIcon;            }        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mIcon;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLoader.getContext().getResources().getDrawable(                android.R.drawable.sym_def_app_icon);    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">toString</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> mLabel;    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> loadLabel(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLabel == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || !mMounted) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mApkFile.exists()) {                mMounted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;                mLabel = mInfo.packageName;            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                mMounted = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;                CharSequence label = mInfo.loadLabel(context.getPackageManager());                mLabel = label != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> ? label.toString() : mInfo.packageName;            }        }    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> AppListLoader mLoader;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ApplicationInfo mInfo;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> File mApkFile;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String mLabel;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Drawable mIcon;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mMounted;}<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Perform alphabetical comparison of application entry objects. */</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Comparator<AppEntry> ALPHA_COMPARATOR = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Comparator<AppEntry>() {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Collator sCollator = Collator.getInstance();    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">compare</span>(AppEntry object1, AppEntry object2) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sCollator.compare(object1.getLabel(), object2.getLabel());    }};<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Helper for determining if the configuration has changed in an interesting * way so we need to rebuild the app list. */</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">InterestingConfigChanges</span> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Configuration mLastConfiguration = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Configuration();    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mLastDensity;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> applyNewConfig(Resources res) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> configChanges = mLastConfiguration.updateFrom(res.getConfiguration());        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE                |ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {            mLastDensity = res.getDisplayMetrics().densityDpi;            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;    }}<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * Helper class to look for interesting changes to the installed apps * so that the loader can be updated. */</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PackageIntentReceiver</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">BroadcastReceiver</span> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> AppListLoader mLoader;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">PackageIntentReceiver</span>(AppListLoader loader) {        mLoader = loader;        IntentFilter filter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IntentFilter(Intent.ACTION_PACKAGE_ADDED);        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);        filter.addDataScheme(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"package"</span>);        mLoader.getContext().registerReceiver(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, filter);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Register for events related to sdcard installation.</span>        IntentFilter sdFilter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IntentFilter();        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);        mLoader.getContext().registerReceiver(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, sdFilter);    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onReceive</span>(Context context, Intent intent) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Tell the loader about the change.</span>        mLoader.onContentChanged();    }}<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * A custom Loader that loads all of the installed applications. */</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppListLoader</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AsyncTaskLoader</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">List</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppEntry</span>>> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> InterestingConfigChanges mLastConfig = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> InterestingConfigChanges();    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> PackageManager mPm;    List<AppEntry> mApps;    PackageIntentReceiver mPackageObserver;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AppListLoader</span>(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Retrieve the package manager for later use; note we don't</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// use 'context' directly but instead the save global application</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// context returned by getContext().</span>        mPm = getContext().getPackageManager();    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * This is where the bulk of our work is done.  This function is     * called in a background thread and should generate a new set of     * data to be published by the loader.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> List<AppEntry> <span class="hljs-title" style="box-sizing: border-box;">loadInBackground</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Retrieve all known applications.</span>        List<ApplicationInfo> apps = mPm.getInstalledApplications(                PackageManager.GET_UNINSTALLED_PACKAGES |                PackageManager.GET_DISABLED_COMPONENTS);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (apps == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            apps = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<ApplicationInfo>();        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Context context = getContext();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Create corresponding array of entries and load their labels.</span>        List<AppEntry> entries = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<AppEntry>(apps.size());        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i<apps.size(); i++) {            AppEntry entry = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AppEntry(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, apps.get(i));            entry.loadLabel(context);            entries.add(entry);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Sort the list.</span>        Collections.sort(entries, ALPHA_COMPARATOR);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Done!</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> entries;    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Called when there is new data to deliver to the client.  The     * super class will take care of delivering it; the implementation     * here just adds a little more logic.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">deliverResult</span>(List<AppEntry> apps) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isReset()) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// An async query came in while the loader is stopped.  We</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// don't need the result.</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (apps != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {                onReleaseResources(apps);            }        }        List<AppEntry> oldApps = mApps;        mApps = apps;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isStarted()) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If the Loader is currently started, we can immediately</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// deliver its results.</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.deliverResult(apps);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// At this point we can release the resources associated with</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 'oldApps' if needed; now that the new result is delivered we</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// know that it is no longer in use.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (oldApps != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            onReleaseResources(oldApps);        }    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Handles a request to start the Loader.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStartLoading</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mApps != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If we currently have a result available, deliver it</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// immediately.</span>            deliverResult(mApps);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Start watching for changes in the app data.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPackageObserver == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            mPackageObserver = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PackageIntentReceiver(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Has something interesting in the configuration changed since we</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// last built the app list?</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> configChange = mLastConfig.applyNewConfig(getContext().getResources());        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (takeContentChanged() || mApps == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || configChange) {            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If the data has changed since the last time it was loaded</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// or is not currently available, start a load.</span>            forceLoad();        }    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Handles a request to stop the Loader.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onStopLoading</span>() {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Attempt to cancel the current load task if possible.</span>        cancelLoad();    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Handles a request to cancel a load.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCanceled</span>(List<AppEntry> apps) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCanceled(apps);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// At this point we can release the resources associated with 'apps'</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// if needed.</span>        onReleaseResources(apps);    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Handles a request to completely reset the Loader.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onReset</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onReset();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Ensure the loader is stopped</span>        onStopLoading();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// At this point we can release the resources associated with 'apps'</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// if needed.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mApps != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            onReleaseResources(mApps);            mApps = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Stop monitoring for changes.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPackageObserver != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            getContext().unregisterReceiver(mPackageObserver);            mPackageObserver = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;        }    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Helper function to take care of releasing resources associated     * with an actively loaded data set.     */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onReleaseResources</span>(List<AppEntry> apps) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// For a simple List<> there is nothing to do.  For something</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// like a Cursor, we would close it here.</span>    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li><li style="box-sizing: border-box; padding: 0px 5px;">240</li><li style="box-sizing: border-box; padding: 0px 5px;">241</li><li style="box-sizing: border-box; padding: 0px 5px;">242</li><li style="box-sizing: border-box; padding: 0px 5px;">243</li><li style="box-sizing: border-box; padding: 0px 5px;">244</li><li style="box-sizing: border-box; padding: 0px 5px;">245</li><li style="box-sizing: border-box; padding: 0px 5px;">246</li><li style="box-sizing: border-box; padding: 0px 5px;">247</li><li style="box-sizing: border-box; padding: 0px 5px;">248</li><li style="box-sizing: border-box; padding: 0px 5px;">249</li><li style="box-sizing: border-box; padding: 0px 5px;">250</li><li style="box-sizing: border-box; padding: 0px 5px;">251</li><li style="box-sizing: border-box; padding: 0px 5px;">252</li><li style="box-sizing: border-box; padding: 0px 5px;">253</li><li style="box-sizing: border-box; padding: 0px 5px;">254</li><li style="box-sizing: border-box; padding: 0px 5px;">255</li><li style="box-sizing: border-box; padding: 0px 5px;">256</li><li style="box-sizing: border-box; padding: 0px 5px;">257</li><li style="box-sizing: border-box; padding: 0px 5px;">258</li><li style="box-sizing: border-box; padding: 0px 5px;">259</li><li style="box-sizing: border-box; padding: 0px 5px;">260</li><li style="box-sizing: border-box; padding: 0px 5px;">261</li><li style="box-sizing: border-box; padding: 0px 5px;">262</li><li style="box-sizing: border-box; padding: 0px 5px;">263</li><li style="box-sizing: border-box; padding: 0px 5px;">264</li><li style="box-sizing: border-box; padding: 0px 5px;">265</li><li style="box-sizing: border-box; padding: 0px 5px;">266</li><li style="box-sizing: border-box; padding: 0px 5px;">267</li><li style="box-sizing: border-box; padding: 0px 5px;">268</li><li style="box-sizing: border-box; padding: 0px 5px;">269</li><li style="box-sizing: border-box; padding: 0px 5px;">270</li><li style="box-sizing: border-box; padding: 0px 5px;">271</li><li style="box-sizing: border-box; padding: 0px 5px;">272</li><li style="box-sizing: border-box; padding: 0px 5px;">273</li><li style="box-sizing: border-box; padding: 0px 5px;">274</li><li style="box-sizing: border-box; padding: 0px 5px;">275</li><li style="box-sizing: border-box; padding: 0px 5px;">276</li><li style="box-sizing: border-box; padding: 0px 5px;">277</li><li style="box-sizing: border-box; padding: 0px 5px;">278</li><li style="box-sizing: border-box; padding: 0px 5px;">279</li><li style="box-sizing: border-box; padding: 0px 5px;">280</li><li style="box-sizing: border-box; padding: 0px 5px;">281</li><li style="box-sizing: border-box; padding: 0px 5px;">282</li></ul>

不用多说,上面Loader为Google出品,强大的不得了,我们完全可以仿写这个例子实现自己的请求。

如下为官方对该自定义Loader调运的Demo代码:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppListAdapter</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ArrayAdapter</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppEntry</span>> {</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> LayoutInflater mInflater;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AppListAdapter</span>(Context context) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context, android.R.layout.simple_list_item_2);        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setData</span>(List<AppEntry> data) {        clear();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (data != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            addAll(data);        }    }    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**     * Populate new items in the list.     */</span>    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> View <span class="hljs-title" style="box-sizing: border-box;">getView</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, View convertView, ViewGroup parent) {        View view;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (convertView == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {            view = mInflater.inflate(R.layout.list_item_icon_text, parent, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            view = convertView;        }        AppEntry item = getItem(position);        ((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());        ((TextView)view.findViewById(R.id.text)).setText(item.getLabel());        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> view;    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppListFragment</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ListFragment</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnQueryTextListener</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">OnCloseListener</span>,        <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderManager</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LoaderCallbacks</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">List</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AppEntry</span>>> {</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is the Adapter being used to display the list's data.</span>    AppListAdapter mAdapter;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The SearchView for doing filtering.</span>    SearchView mSearchView;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If non-null, this is the current filter the user has provided.</span>    String mCurFilter;    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onActivityCreated</span>(Bundle savedInstanceState) {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onActivityCreated(savedInstanceState);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Give some text to display if there is no data.  In a real</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// application this would come from a resource.</span>        setEmptyText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No applications"</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We have a menu item to show in action bar.</span>        setHasOptionsMenu(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Create an empty adapter we will use to display the loaded data.</span>        mAdapter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AppListAdapter(getActivity());        setListAdapter(mAdapter);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Start out with a progress indicator.</span>        setListShown(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Prepare the loader.  Either re-connect with an existing one,</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// or start a new one.</span>        getLoaderManager().initLoader(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MySearchView</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SearchView</span> {</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">MySearchView</span>(Context context) {            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);        }        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The normal SearchView doesn't clear its search text when</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// collapsed, so we will do this for it.</span>        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onActionViewCollapsed</span>() {            setQuery(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onActionViewCollapsed();        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreateOptionsMenu</span>(Menu menu, MenuInflater inflater) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Place an action bar item for searching.</span>        MenuItem item = menu.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Search"</span>);        item.setIcon(android.R.drawable.ic_menu_search);        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM                | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);        mSearchView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MySearchView(getActivity());        mSearchView.setOnQueryTextListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        mSearchView.setOnCloseListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);        mSearchView.setIconifiedByDefault(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        item.setActionView(mSearchView);    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onQueryTextChange</span>(String newText) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Called when the action bar search text has changed.  Since this</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// is a simple array adapter, we can just have it do the filtering.</span>        mCurFilter = !TextUtils.isEmpty(newText) ? newText : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;        mAdapter.getFilter().filter(mCurFilter);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onQueryTextSubmit</span>(String query) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Don't care about this.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onClose</span>() {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!TextUtils.isEmpty(mSearchView.getQuery())) {            mSearchView.setQuery(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        }        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onListItemClick</span>(ListView l, View v, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> id) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Insert desired behavior here.</span>        Log.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LoaderCustom"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Item clicked: "</span> + id);    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Loader<List<AppEntry>> <span class="hljs-title" style="box-sizing: border-box;">onCreateLoader</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> id, Bundle args) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is called when a new Loader needs to be created.  This</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// sample only has one Loader with no arguments, so it is simple.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AppListLoader(getActivity());    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoadFinished</span>(Loader<List<AppEntry>> loader, List<AppEntry> data) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Set the new data in the adapter.</span>        mAdapter.setData(data);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The list should now be shown.</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isResumed()) {            setListShown(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {            setListShownNoAnimation(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);        }    }    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLoaderReset</span>(Loader<List<AppEntry>> loader) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Clear the data in the adapter.</span>        mAdapter.setData(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li></ul>

强大的一逼!这下满技能,不解释,自己看。

4-4 进阶总结

通过前面基础实例、源码分析、进阶演示你会发现Loader的真的非常好用,非常牛逼,牛逼的我不想再解释啥了,自己体会吧。

PS:之前看见微博上有人讨论AsyncTaskLoader与AsyncTask的区别,这下彻底明朗了,看完源码我们再回过头来总结性的说说他们二者区别,如下:

class优势劣势AsyncTaskLoader会自动刷新数据变化;会自动处理Activiy配置变化造成的影响;适合处理纯数据加载;不能实时通知UI刷新;不能在onLoadFinished时主动切换生命周期(譬如replace Fragment);AsyncTask可以与UI实时交互及replace操作;不会自动处理Activiy配置变化造成的影响;


好了,该撕逼的也撕了,该装逼的也装了,该分析的也分析了,该学习的也学到了,接下来就是看自己如何带着Loader去叱诧风云了。

【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】

版权声明:本文为博主原创文章,未经博主允许不得转载。

0 0
原创粉丝点击