項目地址:https://github.com/googlesamples/android-architecture/tree/todo-mvp-loaders/
本項目基于todo-mvp(后文所說”對比之前的項目”,即是說的它),并使用Loaders機制來獲取數據,如圖: 圖示,P通過Loaders獲取數據M 本文MVP相關的就不再重復解釋了
對比之前的項目,多了兩個類: TaskLoader —— 獲取一條Task數據的Loader TasksLoader —— 獲取一個List<Task>數據的Loader
引用一段官方關于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<Task> loadInBackground() { return mRepository.getTasks(); } @Override public void deliverResult(List<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.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<List<Task>> { 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<Task> 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<List<Task>> onCreateLoader(int id, Bundle args) { mTasksView.setLoadingIndicator(true); return mLoader; } @Override public void onLoadFinished(Loader<List<Task>> loader, List<Task> data) { mTasksView.setLoadingIndicator(false); mCurrentTasks = data; if (mCurrentTasks == null) { mTasksView.showLoadingTasksError(); } else { showFilteredTasks(); } } private void showFilteredTasks() { List<Task> 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<List<Task>> onCreateLoader(int id, Bundle args) { mTasksView.setLoadingIndicator(true); return mLoader; }mLoader就被mLoaderManager所管理 當TasksLoader的加載任務開始后,會調用TasksLoader#loadInBackground():
public List<Task> loadInBackground() { return mRepository.getTasks(); }至此,數據加載流程就分析完了。然后再交由View來顯示就是了
而TasksRepository(M,不由P直接操作)、TasksLoader(由P直接操作,它再去操作TasksRepository)、TasksFragment(V)、TasksPresenter(P),都在Activity中進行初始化
新聞熱點
疑難解答