概述
加载器 Loader 支持在 Activity 或 Fragment 中异步加载数据,具有如下几个特点:
- 可用于每个
Activity和Fragment - 支持异步加载数据
- 监控其数据源并在内容变化时传递新结果
- 在某一配置更改后重建
Loader时,会自动重新连接上一个Loader的Cursor,因此它们无需重新查询其数据
API 简介
LoaderManager
与Activity或Fragment相关联的的抽象类,用于管理一个或多个Loader实例。这有助于应用管理与Activity或Fragment生命周期相关联的、运行时间较长的操作。用来管理实例初始化,获取,重启一个Loader。LoaderManager.LoaderCallbacks
回调接口,用于UI与LoaderManager进行交互。执行Loader回调,绑定分发Loader,完成加载,重置数据等。Loader
执行异步数据加载的抽象类,基类。运行异步操作,有开始,完成,后台加载等接口实现。常用CursorLoader或自己定义的子类。AsyncTaskLoader
提供AsyncTask来执行工作的抽象加载器。CursorLoaderAsyncTaskLoader的子类,它将查询ContentResolver并返回一个Cursor。此类采用标准方式为查询游标实现Loader协议。它是以AsyncTaskLoader为基础而构建,在后台线程中执行Cursor查询,以免阻塞应用的UI。使用此加载器是从ContentProvider异步加载数据的最佳方式,而不用通过Fragement或Activity的API来执行托管查询。
使用加载器
LoaderManager 可在 Activity 或 Fragment 内管理一个或多个 Loader 实例;但是每个 Activity 或 Fragment 中只有一个 LoaderManager 。常用接口:
1 | public abstract <D> Loader<D> initLoader(int id, Bundle args, |
启动加载器
通常在 Activity 的 onCreate() 方法或 Fragment 的 onActivityCreated() 方法内初始化 Loader ,如:
1 | // Prepare the loader. Either re-connect with an existing one, |
initLoader() 方法参数解析:
id
用于标识加载器的唯一ID,此示例中为 0args
在构建时提供给加载器的可选参数,可以保存任何数据,示例中为nullcallbackLoaderManager.LoaderCallbacks的实现,LoaderManager将调用此实现来报告加载器事件
注意:
initLoader()方法将返回已创建的Loader,但不必使用该引用,LoaderManager将自动管理加载器的生命周期,根据需要启动和停止加载,并维护加载器的状态及其相关内容。
重启加载器
使用 initLoader() 时,将使用含有指定 ID 的现有加载器。如果没有则它会创建一个。但是如果需要舍弃这些旧数据并重新开始,可以重启加载器:
1 | // 重启加载器,ID必须和初始化时相同 |
使用加载器回调
LoaderManager.LoaderCallbacks 是交互的回调接口,都是在主线程中执行,包括以下方法:
1 | public interface LoaderCallbacks<D> { |
onCreateLoader()
针对指定的ID进行实例化并返回新的LoaderonLoadFinished()
在先前创建的加载器完成加载时调用onLoaderReset()
在先前创建的加载器重置且其数据因此不可用时调用
onCreateLoader 详解
initLoader() 方法检查是否已存在由该 ID 指定的加载器。如果没有它将触发LoaderManager.LoaderCallbacks 方法 onCreateLoader() 。在此方法中,返回新建的加载器。比如:返回 CursorLoader 对 ContentProvider 执行查询时所需的一系列完整信息,查询是异步执行的。
onLoadFinished 详解
当先前创建的加载器完成加载时调用此方法。
一般情况下会使用 CursorLoader 和 CursorAdapter 组合的方式异步更新数据源。其中 CursorLoader 异步加载 Cursor 后,通过 CursorAdapter 的 swapCursor() 方法来更新数据,该方法会返回之前旧的 Cursor ,但是我们不需要手动去关闭这个旧游标,CursorLoader 会在 onLoadFinished 执行完后自动关闭这个旧游标。示例及源码分析:
1 | // 1. 示例 |
onLoaderReset 详解
此方法将在先前创建的加载器重置且其数据因此不可用时调用。通过此回调可以了解何时将释放数据,因而能够及时移除其引用。使用 null 来实现:mAdapter.swapCursor(null);
常用 Loader
类定义:public class Loader<D> {...}
CursorLoader
类定义及构造函数
1 | // 类定义 |
AsyncTaskLoader
public abstract class AsyncTaskLoader<D> extends Loader<D> {...}
自定义 Loader
问题: ????数据是需要两次 cursor 拼接才能完成,该如何实现?