项目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-loaders/
本项目基于todo-mvp(后文所说”对比之前的项目”,即是说的它),并使用Loaders机制来获取数据,如图:
图示,P通过Loaders获取数据M
本文MVP相关的就不再重复解释了
对比之前的项目,多了两个类:
TaskLoader —— 获取一条Task数据的Loader
TasksLoader —— 获取一个List
引用一段官方关于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
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中进行初始化