加载器
我们知道,在Android开发中,一切耗时的操作都不应该放在UI主线程,而应当通过异步机制实现。Android在3.0 后引入了加载器,支持轻松在 Activity 或片段中异步加载数据,为官方所推荐。
- 加载器具有以下特征
- 可用于每个 Activity 和 Fragment
- 支持异步加载数据
- 监控其数据源并在内容变化时传递新结果
- 在某一配置更改后重建加载器时,会自动重新连接上一个加载器的游标。 因此,它们无需重新查询其数据(由安卓系统框架提供,有单独生命周期,会被自动回收且不必在后台运行)
- 以上叙述部分参考Loader官方指南,欲知Loader详情请点击查看。
- 为什么不要再UI主线程中进行耗时操作?英文原文&中文译文
- 本文将基于MVP架构对Loader进行分析,关于官方MVP架构可以参考我的另一片博文《Android官方MVP示例学习分析》
加载器工作机制
- 我们在提到Loader的时候会涉及到以下几个类/接口,下面对几个类/接口的简单解释,具体请见官方指南:
- LoaderManager:用于管理一个或多个Loader实例
- LoaderManager.LoaderCallbacks:响应Loader和LoaderManager触发的各种事件
- Loader:具体数据加载器,不具有异步加载功能
- AsyncTaskLoader:继承Loader,具有异步加载功能,要实现具体异步加载的逻辑
- CursorLoader:在后台执行游标查询,使用此加载器是从 ContentProvider 异步加载数据的最佳方式。
官方项目运行
仅从项目运行效果而言,MVP+Loader与Android官方MVP架构中无异,唯一的区别在于:
- MVP架构中,如果退出应用再打开,上次设定的任务不会保留。
- MVP+Loader中,如果退出应用再打开,还能看到上次设定的任务,这根上面提到的有关:Loader由安卓系统框架提供,有单独生命周期,会被自动回收且不必在后台运行。
代码分析
我们侧重分析跟Loader相关的部分,其余分析见《Android官方MVP示例学习分析》
Loader加载数据都在Presenter中处理:
TaskDetailPresenter.java
public class TaskDetailPresenter implements TaskDetailContract.Presenter, LoaderManager.LoaderCallbacks<Task> {
...
private TaskLoader mTaskLoader;
private LoaderManager mLoaderManager;
@Override
public void start() {
mLoaderManager.initLoader(TASK_QUERY, null, this);
}
@Override
public Loader<Task> onCreateLoader(int id, Bundle args) {
if (mTaskId == null) {
return null;
}
mTaskDetailView.setLoadingIndicator(true);
return mTaskLoader;
}
@Override
public void onLoadFinished(Loader<Task> loader, Task data) {
if (data != null) {
showTask(data);
} else {
mTaskDetailView.showMissingTask();
}
}
@Override
public void onLoaderReset(Loader<Task> loader) {
}
...
}
而在TaskLoader.java中,实现了接口TaskRepository.TaskRepositoryObserver,当Task发生变化时通知Loader重新加载数据。
public class TaskLoader extends AsyncTaskLoader<Task>
implements TasksRepository.TasksRepositoryObserver{
...
@Override
public Task loadInBackground() {
return mRepository.getTask(mTaskId);
}
@Override
public void deliverResult(Task data) {
if (isReset()) {
return;
}
if (isStarted()) {
super.deliverResult(data);
}
}
@Override
protected void onStartLoading() {
if (mRepository.cachedTasksAvailable()) {
deliverResult(mRepository.getCachedTask(mTaskId));
}
mRepository.addContentObserver(this);
if (takeContentChanged() || !mRepository.cachedTasksAvailable()) {
forceLoad();
}
}
@Override
protected void onReset() {
onStopLoading();
mRepository.removeContentObserver(this);
}
@Override
public void onTasksChanged() {
if (isStarted()) {
forceLoad();
}
}
}
总结
通过上面这个例子,我们理解了Loader的代码实现跟工作原理,下面我们来总结一下:

官方MVP+Loader的结构示意图如上,可以看出Loader在项目中所起的作用。
通过使用Loader,我们可以在任何一个Activity/Fragment中,使用异步加载机制,当数据源产生变化时传递结果更改UI。同时当Activity配置发生改变时,不需重新加载数据。
基于这些优势,在实际应用中Loader具有重要的意义。
代码来源见:官方项目地址 |