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

项目结构

本项目基于todo-mvp(后文所说”对比之前的项目”,即是说的它),并使用Loaders机制来获取数据,如图:

图示,P通过Loaders获取数据M
本文MVP相关的就不再重复解释了

data模块


对比之前的项目,多了两个类:
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. Android的Handler总结
  2. android ContentProvider使用详解
  3. 【Android(安卓)Dev Guide - 03】 - Content Providers
  4. Android中包含多个Activity的应用退出按钮实现
  5. Android:WebService
  6. Android基础类之BaseAdapter
  7. MediaPlayer框架概述(一)
  8. Android(安卓)Http通信
  9. mybatisplus的坑 insert标签insert into select无参数问题的解决

随机推荐

  1. android之用户定位(一)
  2. Android(安卓)的实现TextView中文字链接
  3. Android中的五大存储
  4. 引用 Android上dip、dp、px、sp等单位说
  5. Android(安卓)中屏幕点击事件的实现
  6. Android(安卓)系统服务管家servicemanage
  7. Android(安卓)QQ、微信聊天消息界面设计
  8. Android浮动窗口实现原理及代码实例
  9. Android(安卓)框架层为IMountService 增
  10. android taskAffinity属性