源码分析:LoaderManager对Loader的管理

本文主要从Loader入手, 去分析Loader使用、Loader的源码分析等,主要分为以下四篇:

本文基于原生的 Android8.0源码进行分析。以下是第三篇内容

LoaderManager对Loader的管理

1.Loader的创建

我们在使用LoaderManager/Loader时, 通常都会写这么一行代码:

 getLoaderManager().initLoader(0, null, this);  

getLoaderManager()在前面讲到了, 就是去得到一个LoaderManager(实际上是一个LoaderManagerImpl):

LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
    if (mAllLoaderManagers == null) {
        mAllLoaderManagers = new ArrayMap<String, LoaderManager>();
    }
    LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
    if (lm == null && create) {
        lm = new LoaderManagerImpl(who, this, started);
        mAllLoaderManagers.put(who, lm);
    } else if (started && lm != null && !lm.mStarted){
        lm.doStart();
    }
    return lm;
}

我们去看看initLoader:

 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 (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 {
        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;
}

这里首先看到的是在mLoaders中通过id去查询是否有Loader对象,有则直接复用,没有则创建一个。这里可以初步确定,所有的Loader对象都是存放在mLoaders中的最终返回的是Loader对象是info.mLoader, 而info是通过createAndInstallLoader 创建的一个LoaderInfo对象, 进入这个方法看一看:

private LoaderInfo createAndInstallLoader(int id, Bundle args,
        LoaderManager.LoaderCallbacks<Object> callback) {
    try {
        mCreatingLoader = true;
        LoaderInfo info = createLoader(id, args, callback);
        installLoader(info);
        return info;
    } finally {
        mCreatingLoader = false;
    }
}

这里有事通过createLoader方法创建的:

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;
}

从这里我们看到,Loader loader = callback.onCreateLoader(id, args), Loader实际上就是我们在callback接口中的onCreateLoader()这个方法中去创建的Loader, 然后将id, args,Loader一起封装进了LoaderInfo这个对象中。

2.Loader的启动及数据加载

在上面提到的createAndInstallLoader方法中,创建好Loader以后,我们看到调用了方法 installLoader(info):

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();
    }
}

这里看到,info保存在了mLoaders中。然后进入info.start()方法,关键代码如下:

void start() {
    ......
        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();
        }
    }

在这个方法中,首先注册了两个Listener, 分别是数据加载完成和取消加载的监听,这个在后面数据加载完成或者取消加载后会用到。 然后调用了startLoading()方法:

public final void startLoading() {
    mStarted = true;
    mReset = false;
    mAbandoned = false;
    onStartLoading();
}

然后进入onStartLoading():

 /**
 * Subclasses must implement this to take care of loading their data,
 * as per {@link #startLoading()}.  This is not called by clients directly,
 * but as a result of a call to {@link #startLoading()}.
 */
protected void onStartLoading() {
}

onStartLoading在Loader中注释子类必须实现, 而AsyncTaskLoader也没实现这个方法, 所以,这也是为什么前面提到我们自定义的Loader如果继承了AsyncTaskLoader必须实现onStartLoading()这个方法的原因。并且,如果需要真正加载数据,在onStartLoading()方法中还必须调用forceLoad()方法, 我们进入forceLoad()看看, 数据开始加载的逻辑:

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

这里, 去new了一个LoadTask, 然后执行这个LoadTask, 我们先看看这个LoaderTask:

final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {

    /* Runs on a worker thread */
    @Override
    protected D doInBackground(Void... params) {
        try {
            D data = AsyncTaskLoader.this.onLoadInBackground();
            return data;
        } catch (OperationCanceledException ex) {
            if (!isCancelled()) {
                throw ex;
            }
            return null;
        }
    }

    /* Runs on the UI thread */
    @Override
    protected void onPostExecute(D data) {
        try {
            AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
        } finally {
            mDone.countDown();
        }
    }   
......
}

可以看到继承自AsyncTask, 并实现了Runnable接口, 我们知道AsyncTask主要是用来做异步操作任务的,这里也间接说明了这个数据加载是异步的。在doInBackground方法中调用了onLoadInBackground()方法, 最终调用了我们自己实现的doInBackground()方法,然后返回数据, 而onPostExecute()方法则在数据完成后, 往下分发了数据, 通过调用dispatchOnLoadComplete(), 而前面提到,在info.start()方法中注册了数据完成的监听,这里最终调用了onLoadFinished()方法, 从而把加载完毕的数据回调给了业务逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值