LoaderManager源码分析之一

    xiaoxiao2021-03-26  3

    1, 基本概念

    LoaderManager从名字来看,就是异步任务的意思。

    LoaderManager是一个抽象类定义如下,

    public abstract class LoaderManager {

    还包含一个接口,有三个方法,

    public interface LoaderCallbacks<D> { public Loader<D> onCreateLoader(int id, Bundle args); public void onLoadFinished(Loader<D> loader, D data); public void onLoaderReset(Loader<D> loader); }

    实际上, 内部类LoaderManagerImpl是LoaderManager的代理类,负责所有方法的执行。

    LoaderManager定义如下,

    class LoaderManagerImpl extends LoaderManager {

    2, LoaderManager使用

    源码中Contacts加载联系人就利用了LoaderManager机制,实现也很简单,继承LoaderCallbacks接口并且实现三个方法就可以了。

    ContactEntryListFragment中的实现如下,

    导入包

    import android.app.LoaderManager; import android.app.LoaderManager.LoaderCallbacks;

    继承LoaderCallbacks接口

    implements LoaderCallbacks<Cursor>

    实现方法,

    onCreateLoader方法

    public Loader<Cursor> onCreateLoader(int id, Bundle args) { if (id == DIRECTORY_LOADER_ID) { ••• } else { CursorLoader loader = createCursorLoader(mContext); long directoryId = args != null && args.containsKey(DIRECTORY_ID_ARG_KEY) ? args.getLong(DIRECTORY_ID_ARG_KEY) : Directory.DEFAULT; mAdapter.configureLoader(loader, directoryId); return loader; } } public CursorLoader createCursorLoader(Context context) { return new CursorLoader(context, null, null, null, null, null) { @Override protected Cursor onLoadInBackground() { try { return super.onLoadInBackground(); } catch (RuntimeException e) { // We don't even know what the projection should be, so no point trying to // return an empty MatrixCursor with the correct projection here. Log.w(TAG, "RuntimeException while trying to query ContactsProvider."); return null; } } }; }onLoadFinished方法如下,使用完成之后,要调用destroyLoader方法。

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { ••• mDirectoryListStatus = STATUS_NOT_LOADED; getLoaderManager().destroyLoader(DIRECTORY_LOADER_ID); }

    onLoaderReset是一个空的方法,

    public void onLoaderReset(Loader<Cursor> loader) { }

    还需要借助于CursorLoader来实现异步查询。

    Activity/Fragment 中的getLoaderManager 最后获取的是LoaderManagerImpl对象。

    3, 加载原理

    异步加载主要分为以下几个步骤,

    3.1, initLoader

    调用流程图如下,

    LoaderManagerImpl的initLoader方法如下,

    Callback指继承LoaderCallbacks接口的类对象。

    public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { if (mCreatingLoader) { throw new IllegalStateException("Called while creating a loader"); } LoaderInfo info = mLoaders.get(id); if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); if (info == null) { // Loader doesn't already exist; create. info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); if (DEBUG) Log.v(TAG, " Created new loader " + info); } else { if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback; } if (info.mHaveData && mStarted) { // If the loader has already generated its data, report it now. info.callOnLoadFinished(info.mLoader, info.mData); } return (Loader<D>)info.mLoader; }

    createAndInstallLoader代码如下,

    private LoaderInfo createAndInstallLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callback) { try { mCreatingLoader = true; LoaderInfo info = createLoader(id, args, callback); // 构造LoaderInfo对象 installLoader(info); // 对LoaderInfo进行初始化 return info; } finally { mCreatingLoader = false; } }

    createLoader首先构造一个内部类LoaderInfo对象,然后回调ContactEntryListFragment的onCreateLoader方法创建Loader对象,

    实际上是CursorLoader对象。最后将CursorLoader对象作为LoaderInfo对象的mLoader变量。

    private LoaderInfo createLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callback) { LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); Loader<Object> loader = callback.onCreateLoader(id, args); info.mLoader = (Loader<Object>)loader; return info; }

    LoaderInfo类似于一个中间人的角色。

    void installLoader(LoaderInfo info) { mLoaders.put(info.mId, info); if (mStarted) { // The activity will start all existing loaders in it's onStart(), // so only start them here if we're past that point of the activitiy's // life cycle info.start(); } }

    LoaderInfo的start方法如下,

    void start() { if (mRetaining && mRetainingStarted) { // Our owner is started, but we were being retained from a // previous instance in the started state... so there is really // nothing to do here, since the loaders are still started. mStarted = true; return; } if (mStarted) { // If loader already started, don't restart. return; } mStarted = true; if (DEBUG) Log.v(TAG, " Starting: " + this); if (mLoader == null && mCallbacks != null) { mLoader = mCallbacks.onCreateLoader(mId, mArgs); } if (mLoader != null) { if (mLoader.getClass().isMemberClass() && !Modifier.isStatic(mLoader.getClass().getModifiers())) { throw new IllegalArgumentException( "Object returned from onCreateLoader must not be a non-static inner member class: " + mLoader); } if (!mListenerRegistered) { // 是否注册 mLoader.registerListener(mId, this); mLoader.registerOnLoadCanceledListener(this); mListenerRegistered = true; } mLoader.startLoading(); } }

    initLoader方法第一步主要是创建LoaderInfo对象,回调ContactEntryListFragment的onCreateLoader方法创建Loader对象, 以及对LoaderInfo的变量状态赋值。

    3.2, startLoading

    流程图如下,

    2个注册监听方法在后面再论述,先论述startLoading方法,到此,开始异步加载了。

    开始几个方法兜兜转转,最后会调用onForceLoad方法,该方法如下,

    protected void onForceLoad() { super.onForceLoad(); cancelLoad(); mTask = new LoadTask(); if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask); executePendingTask(); }

    LoadTask继承AsyncTask类,重写了

    doInBackground/ onPostExecute/ onCancelled等方法。

    executePendingTask方法如下,

    void executePendingTask() { if (mCancellingTask == null && mTask != null) { if (mTask.waiting) { mTask.waiting = false; mHandler.removeCallbacks(mTask); } if (mUpdateThrottle > 0) { long now = SystemClock.uptimeMillis(); if (now < (mLastLoadCompleteTime+mUpdateThrottle)) { // Not yet time to do another load. if (DEBUG) Log.v(TAG, "Waiting until " + (mLastLoadCompleteTime+mUpdateThrottle) + " to execute: " + mTask); mTask.waiting = true; mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle); return; } } if (DEBUG) Log.v(TAG, "Executing: " + mTask); mTask.executeOnExecutor(mExecutor, (Void[]) null); } }

    直接调用LoadTask的executeOnExecutor方法开始异步查询。

    mExecutor变量在构造方法中赋值为AsyncTask.THREAD_POOL_EXECUTOR。

    关于这个THREAD_POOL_EXECUTOR线程池以及AsyncTask原理在此就不论述了。

    private final Executor mExecutor; public AsyncTaskLoader(Context context) { this(context, AsyncTask.THREAD_POOL_EXECUTOR); } /** {@hide} */ public AsyncTaskLoader(Context context, Executor executor) { super(context); mExecutor = executor; }
    转载请注明原文地址: https://ju.6miu.com/read-500130.html

    最新回复(0)