项目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-loaders/

项目结构

本项目基于todo-mvp(后文所说”对比之前的项目”,即是说的它),并使用Loaders机制来获取数据,如图:
Android 官方示例:android-architecture 学习笔记(三)之todo-mvp-loaders_第1张图片
图示,P通过Loaders获取数据M
本文MVP相关的就不再重复解释了

data模块

Android 官方示例:android-architecture 学习笔记(三)之todo-mvp-loaders_第2张图片
对比之前的项目,多了两个类:
TaskLoader —— 获取一条Task数据的Loader
TasksLoader —— 获取一个List数据的Loader

TasksLoader分析

引用一段官方关于Loaders的中文解释:

Android 3.0 中引入了加载器(即Loaders),支持轻松在 Activity 或片段中异步加载数据。 加载器具有以下特征:

可用于每个 Activity 和 Fragment。
支持异步加载数据。
监控其数据源并在内容变化时传递新结果。
在某一配置更改后重建加载器时,会自动重新连接上一个加载器的游标。 因此,它们无需重新查询其数据。

TasksLoader完整源码:

public class TasksLoader extends AsyncTaskLoader<List<Task>>        implements TasksRepository.TasksRepositoryObserver{    private TasksRepository mRepository;    public TasksLoader(Context context, @NonNull TasksRepository repository) {        super(context);        checkNotNull(repository);        mRepository = repository;    }    @Override    public List loadInBackground() {        return mRepository.getTasks();    }    @Override    public void deliverResult(List 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.getCachedTasks());        }        // 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 onStopLoading() {        cancelLoad();    }    @Override    protected void onReset() {        onStopLoading();        mRepository.removeContentObserver(this);    }    @Override    public void onTasksChanged() {        if (isStarted()) {            forceLoad();        }    }}

分析如上代码:
a. TasksLoader继承了AsyncTaskLoader,并实现TasksRepository.TasksRepositoryObserver接口
b. 结合LoaderManager、Loader、AsyncTaskLoader源码(这里就不全贴了)与官方文档,可分析出几个重写方法的调用周期:
onStartLoading —— 开始加载数据
loadInBackground —— 在后台加载数据,即异步线程
deliverResult —— 加载完成数据后,进行分发,通过追源码,其实就是在Loader中定义了一个回调接口,可以用于处理
onStopLoading —— 停止加载数据
onReset —— 当需要回收destroy时,由LoaderManger调用
c. onStartLoading() 代码解释:如果数据仓库中缓存了数据,则直接分发;注册数据改变的观察接口;若数据改变 或 首次加载未缓存时,调用forceLoad()
d. forceLoad() 调用 AsyncTaskLoader#onForceLoad(),从而开始数据异步加载任务

tasks模块分析

接下来挑一个业务模块分析一下(其它模块大同小异),比如tasks
TasksPresenter主要代码:

public class TasksPresenter implements TasksContract.Presenter,        LoaderManager.LoaderCallbacks> {    private final static int TASKS_QUERY = 1;    private final TasksRepository mTasksRepository;    private final TasksContract.View mTasksView;    private final TasksLoader mLoader;    private final LoaderManager mLoaderManager;    private List mCurrentTasks;    private TasksFilterType mCurrentFiltering = TasksFilterType.ALL_TASKS;    private boolean mFirstLoad;    public TasksPresenter(@NonNull TasksLoader loader, @NonNull LoaderManager loaderManager,                          @NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {        mLoader = checkNotNull(loader, "loader cannot be null!");        mLoaderManager = checkNotNull(loaderManager, "loader manager cannot be null");        mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");        mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");        mTasksView.setPresenter(this);    }    @Override    public void start() {        mLoaderManager.initLoader(TASKS_QUERY, null, this);    }    @Override    public Loader> onCreateLoader(int id, Bundle args) {        mTasksView.setLoadingIndicator(true);        return mLoader;    }    @Override    public void onLoadFinished(Loader> loader, List data) {        mTasksView.setLoadingIndicator(false);        mCurrentTasks = data;        if (mCurrentTasks == null) {            mTasksView.showLoadingTasksError();        } else {            showFilteredTasks();        }    }    private void showFilteredTasks() {        List tasksToDisplay = new ArrayList<>();        if (mCurrentTasks != null) {            for (Task task : mCurrentTasks) {                switch (mCurrentFiltering) {                    case ALL_TASKS:                        tasksToDisplay.add(task);                        break;                    case ACTIVE_TASKS:                        if (task.isActive()) {                            tasksToDisplay.add(task);                        }                        break;                    case COMPLETED_TASKS:                        if (task.isCompleted()) {                            tasksToDisplay.add(task);                        }                        break;                    default:                        tasksToDisplay.add(task);                        break;                }            }        }        processTasks(tasksToDisplay);    }}

在start()中,

mLoaderManager.initLoader(TASKS_QUERY, null, this);

初始化了LoaderManager,则会调用

    @Override    public Loader> onCreateLoader(int id, Bundle args) {        mTasksView.setLoadingIndicator(true);        return mLoader;    }

mLoader就被mLoaderManager所管理
当TasksLoader的加载任务开始后,会调用TasksLoader#loadInBackground():

 public List loadInBackground() {        return mRepository.getTasks();    }

至此,数据加载流程就分析完了。然后再交由View来显示就是了

而TasksRepository(M,不由P直接操作)、TasksLoader(由P直接操作,它再去操作TasksRepository)、TasksFragment(V)、TasksPresenter(P),都在Activity中进行初始化

更多相关文章

  1. React Native 中的 Android 原生模块
  2. 嵌入数据库SQLite(3) - Android
  3. Java加载js
  4. Android中使用xml保存数据(xml文件序列化)及使用pull解析xml文件
  5. android读取sqlite数据库的数据并用listview显示
  6. 【Android】数据存储之Shared Preferences

随机推荐

  1. 区块链交易所:虚拟货币交易的5个技巧
  2. 三十分钟做一个网页游戏
  3. 开始着手用Python写一个游戏脚本
  4. 游戏开发完整学习路线,都在这里了
  5. Java文件上传实例并解决跨域问题
  6. 盘点市面上主流的时序数据库
  7. TCP协议为什么需要三次握手?
  8. Html基本语法
  9. HTML表单内容的详细介绍
  10. html练习之表单标签使用