Android 官方示例:android-architecture 学习笔记(六)之todo-mvp-contentproviders
项目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-contentproviders/项目结构本项目基于todo-mvp-loaders,并使用Content Provider来检索数据。架构图:源码分析这次从taskdetail模块的入口开始分析TaskDetailActivity —— 初始化了
项目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-contentproviders/
项目结构
本项目基于todo-mvp-loaders,并使用Content Provider来检索数据。架构图:
源码分析
这次从taskdetail模块的入口开始分析
TaskDetailActivity —— 初始化了TaskDetailFragment、LoaderProvider、TaskDetailPresenter。
LoaderProvider 代码:
public class LoaderProvider {
@NonNull
private final Context mContext;
public LoaderProvider(@NonNull Context context) {
mContext = checkNotNull(context, "context cannot be null");
}
public Loader<Cursor> createFilteredTasksLoader(TaskFilter taskFilter) {
String selection = null;
String[] selectionArgs = null;
switch (taskFilter.getTasksFilterType()) {
case ALL_TASKS:
selection = null;
selectionArgs = null;
break;
case ACTIVE_TASKS:
selection = TasksPersistenceContract.TaskEntry.COLUMN_NAME_COMPLETED + " = ? ";
selectionArgs = new String[]{String.valueOf(0)};
break;
case COMPLETED_TASKS:
selection = TasksPersistenceContract.TaskEntry.COLUMN_NAME_COMPLETED + " = ? ";
selectionArgs = new String[]{String.valueOf(1)};
break;
}
return new CursorLoader(
mContext,
TasksPersistenceContract.TaskEntry.buildTasksUri(),
TasksPersistenceContract.TaskEntry.TASKS_COLUMNS, selection, selectionArgs, null
);
}
public Loader<Cursor> createTaskLoader(String taskId) {
return new CursorLoader(mContext, TasksPersistenceContract.TaskEntry.buildTasksUriWith(taskId),
null,
null,
new String[]{String.valueOf(taskId)}, null
);
}
}
主要是提供了两种创建CursorLoader的方法。
TaskDetailFragment —— 实现TaskDetailContract.View接口,组合使用了TaskDetailContract.Presenter
TaskDetailPresenter 代码:
public class TaskDetailPresenter implements TaskDetailContract.Presenter, LoaderManager.LoaderCallbacks<Cursor>,TasksDataSource.GetTaskCallback {
public final static int TASK_LOADER = 2;
@NonNull
private final TasksRepository mTasksRepository;
private TaskDetailContract.View mTaskDetailView;
private LoaderProvider mLoaderProvider;
private LoaderManager mLoaderManager;
private Task mTask;
private String mTaskId;
public TaskDetailPresenter(@NonNull String taskId,
@NonNull LoaderProvider loaderProvider,
@NonNull LoaderManager loaderManager,
@NonNull TasksRepository tasksRepository,
@NonNull TaskDetailContract.View taskDetailView) {
mTaskId = checkNotNull(taskId, "taskId cannot be null!");
mLoaderProvider = checkNotNull(loaderProvider, "loaderProvider cannot be null!");
mLoaderManager = checkNotNull(loaderManager, "loaderManager cannot be null!");
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null!");
mTaskDetailView = checkNotNull(taskDetailView, "taskDetailView cannot be null!");
mTaskDetailView.setPresenter(this);
}
@Override
public void start() {
loadTask();
}
private void loadTask() {
mTaskDetailView.setLoadingIndicator(true);
mTasksRepository.getTask(mTaskId, this);
}
@Override
public void editTask() {
if (null == mTask) {
mTaskDetailView.showMissingTask();
return;
}
mTaskDetailView.showEditTask(mTask.getId());
}
@Override
public void deleteTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.deleteTask(mTaskId);
mTaskDetailView.showTaskDeleted();
}
public void completeTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.completeTask(mTask);
mTaskDetailView.showTaskMarkedComplete();
}
@Override
public void activateTask() {
if (Strings.isNullOrEmpty(mTaskId)) {
mTaskDetailView.showMissingTask();
return;
}
mTasksRepository.activateTask(mTask);
mTaskDetailView.showTaskMarkedActive();
}
private void showTask(Cursor data) {
mTask = Task.from(data);
String title = mTask.getTitle();
String description = mTask.getDescription();
if (Strings.isNullOrEmpty(title)) {
mTaskDetailView.hideTitle();
} else {
mTaskDetailView.showTitle(title);
}
if (Strings.isNullOrEmpty(description)) {
mTaskDetailView.hideDescription();
} else {
mTaskDetailView.showDescription(description);
}
mTaskDetailView.showCompletionStatus(mTask.isCompleted());
mTaskDetailView.setLoadingIndicator(false);
}
public void onDataLoaded(Cursor data) {
showTask(data);
}
public void onDataEmpty() {
mTaskDetailView.showMissingTask();
}
@Override
public void onTaskLoaded(Task task) {
// the data is refreshed locally now but
// we don't need this result since the CursorLoader will load it for us
mLoaderManager.initLoader(TASK_LOADER, null, this);
}
public void onDataNotAvailable() {
mTaskDetailView.showMissingTask();
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return mLoaderProvider.createTaskLoader(mTaskId);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null) {
if (data.moveToLast()) {
onDataLoaded(data);
} else {
onDataEmpty();
}
} else {
onDataNotAvailable();
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// no-op
}
}
结合之前MVP和Loaders项目来分析。start(),会被fragment.onResume()调用,它是一个默认的执行流程入口。srtart()->loadTask()->mTasksRepository.getTask(mTaskId, this),至此就会从仓库获取数据Task。this指代的是GetTaskCallback,对应的回调方法为onTaskLoaded()。onTaskLoaded()中初始化Loader,会再继续执行LoaderCallbacks的方法:onCreateLoader()、onLoadFinished()。onLoadFinished()中,获取到数据后,会调用onDataLoaded()。最终将数据显示TaskDetailView(V)上。
再分析下TasksRepository 是如何操作数据的。这里就直接说了,它是直接通过TasksLocalDataSource来操作数据的。TasksLocalDataSource中使用了ContentResolver。ContentResolver操作的ContentProvider就是TasksProvider。
注:ContentProvider是可以为当前或其他App提供共享数据的。通过一套Uri匹配规则,由ContentResolver发起调用。ContentProvider的底层数据存储不局限于DB方式。
更多推荐


所有评论(0)