Android官方MVP+Loader示例学习

加载器

  我们知道,在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 异步加载数据的最佳方式。

      Android官方MVP+Loader示例学习_第1张图片

官方项目运行

  仅从项目运行效果而言,MVP+Loader与Android官方MVP架构中无异,唯一的区别在于:

  • MVP架构中,如果退出应用再打开,上次设定的任务不会保留。
  • MVP+Loader中,如果退出应用再打开,还能看到上次设定的任务,这根上面提到的有关:Loader由安卓系统框架提供,有单独生命周期,会被自动回收且不必在后台运行。

代码分析

我们侧重分析跟Loader相关的部分,其余分析见《Android官方MVP示例学习分析》
Loader加载数据都在Presenter中处理:

TaskDetailPresenter.java

public class TaskDetailPresenter implements TaskDetailContract.Presenter, LoaderManager.LoaderCallbacks {
    ...
//TaskLoader和LoaderManager变量的声明
    private TaskLoader mTaskLoader;
    private LoaderManager mLoaderManager;

//启动Loader,检查是否存在加载器。若不存在,默认调用onCreateLoader()
    @Override
    public void start() {
        mLoaderManager.initLoader(TASK_QUERY, null, this);
    }

//通过LoaderManager.LoaderCallbacks创建loader
    @Override
    public Loader onCreateLoader(int id, Bundle args) {
        if (mTaskId == null) {
            return null;
        }
        mTaskDetailView.setLoadingIndicator(true);
        return mTaskLoader;
    }

//加载完成后,通过LoaderManager.LoaderCallbacks显示数据
    @Override
    public void onLoadFinished(Loader loader, Task data) {
        if (data != null) {
            showTask(data);
        } else {
            mTaskDetailView.showMissingTask();
        }
    }

    @Override
    public void onLoaderReset(Loader loader) {
        // no-op
    }
    ...
}

而在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() {

        // Deliver any previously loaded data immediately if available.
        if (mRepository.cachedTasksAvailable()) {
            deliverResult(mRepository.getCachedTask(mTaskId));
        }

        // Begin monitoring the underlying data source.
        mRepository.addContentObserver(this);

        if (takeContentChanged() || !mRepository.cachedTasksAvailable()) {
            // When a change has  been delivered or the repository cache isn't available, we force
            // a load.
            forceLoad();
        }
    }

//重置时调用
    @Override
    protected void onReset() {
        onStopLoading();
        mRepository.removeContentObserver(this);
    }

    @Override
    public void onTasksChanged() {
        if (isStarted()) {
            forceLoad();
        }
    }
}

总结

  通过上面这个例子,我们理解了Loader的代码实现跟工作原理,下面我们来总结一下:
  Android官方MVP+Loader示例学习_第2张图片

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

代码来源见:官方项目地址

你可能感兴趣的:(Android)