LoaderManager源码分析
LoaderManager是与Activity或者Fragment相关联的接口,用于管理与其关联一个或者多个Loader的实例。有助于应用程序长时间管理Activity或者Fragment的生命周期的操作。常见的用途是使用CursorLoader。下面的链接是一个Fragment的完整实现,它显示了一个包含对联系人内容提供者的查询结果的ListView。 它使用CursorLoader来管理提供者上的查询操作。
https://developer.android.com/reference/android/app/LoaderManager.html
总结:
虽然这个类已经看完了,各个方法大致直到是什么意思,但是想要搞明白,还需要看看其它的相关联的类,FragmentController,和它的实现类FragmentHostCallback,FragmentManager,想要查看调用链需要阅读这三个类。
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);
}
LoaderCallbacks是客户端与管理器的回调接口。
-
onCreateLoader:
实例化并为给定的ID返回一个新的Loader。
param id要加载的ID
调用者提供的参数
return返回一个可以开始加载的新的Loader实例。 -
onLoadFinished:
onCreateLoader创建的加载器完成加载时调用,注意应用程序不允许提交Fragment的事务,因为可能会在保存活动状态后发生,请参阅FragmentManager.openTransaction()。
这个函数能在释放资源时,能够返回最后一次数据。在这个回调中,应该删除上一次的数据,加载最新的数据,但是不应该去自己去发布数据,由Loader自己去处理,loader只负责管理数据。
不要去做下面的事情:
-
Loader会监听数据的变化,并会通过这个方法通知你,不应该自己去监听数据。例如,如果数据是一个Cursor,并将其放置在CursorAdapter中,则使用CursorAdapter(android.content.Context,android.database.Cursor,int)构造函数,而不传入FLAG_AUTO_REQUERY或FLAG_REGISTER_CONTENT_OBSERVER(即,使用0作为标志参数)。这可以防止CursorAdapter自己观察游标,因为当发生变化时,您将得到一个新的游标在这里再次调用游标。
-
一旦应用程序不在使用Loader,Loader将释放数据。例如,如果数据是来自CursorLoader的Cursor,则不应该自己调用close()。如果光标放在CursorAdapter中,则应该使用swapCursor(android.database.Cursor)方法,以便旧的光标未关闭。
Parameters
loader Loader: The Loader that has finished.
data D: The data generated by the Loader.
- onLoaderReset
在之前创建的加载程序正在重置时调用,从而使其数据不可用。 应用程序应该删除对Loader数据的任何引用。
- initLoader
public abstract <D> Loader<D> initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);
确保加载程序已初始化并处于活动状态。 如果加载器尚不存在,则创建一个加载器(如果活动/片段当前已启动)将启动加载器。 否则,重新使用最后创建的加载器。
在任何情况下,给定的回调都与加载器相关联,并且将在loader状态更改时调用。 如果在调用点处调用者处于启动状态,并且请求的加载器已经存在并且已经生成了它的数据,那么将立即调用onLoadFinished(Loader,D)的回调函数(在这个函数内部),所以你必须准备好 为此发生。
- restartLoader
public abstract <D> Loader<D> restartLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);
manager会新建一个或者重新启动一个存在的Loader,注册回调,(如果当前的Activity或者Fragment启动)开始加载。如果之前已经启动了相同的Id的加载器,在新的Loader加载数据完成时,旧的Loader会被自动销毁。在销毁之前,回调会被发送出来。
- destroyLoader
public abstract void destroyLoader(int id);
停止并删除具有指定id的Loader。如果Loader以前通过onLoadFinished(Loader, Object)向客户端发送过数据,则会调用onLoaderReset(Loader)。
- getLoader
public abstract <D> Loader<D> getLoader(int id);
如果没有找到匹配的Loader,则返回给定id的Loader或null
- hasRunningLoaders
public boolean hasRunningLoaders() { return false; }
如果管理的加载器当前正在运行,并且还没有将数据返回给应用程序,则返回true。
LoaderManagerImpl是LoaderManager实现类
这里主要看LoaderManagerImpl实现类和LoaderInfo内部类。
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);
}
public abstract <D> Loader<D> initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);
public abstract <D> Loader<D> restartLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);
public abstract void destroyLoader(int id);
public abstract <D> Loader<D> getLoader(int id);
public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
public static void enableDebugLogging(boolean enabled) {
LoaderManagerImpl.DEBUG = enabled;
}
public boolean hasRunningLoaders() { return false; }
}
class LoaderManagerImpl extends LoaderManager {
static final String TAG = "LoaderManager";
static boolean DEBUG = false;
// These are the currently active loaders. A loader is here
// from the time its load is started until it has been explicitly
// stopped or restarted by the application.
//这些是当前活跃的Loader,Loader从开始加载直到它明确的要求被消应用程序停止或者重新开启。
//SparseArrayCompat数据类似与hashMap,使用方法类似与hashMap。
//优点,最高节省50%的缓存。
//缺点就是key只能是Integer类型,value只能是object类型。因此当HshMap()的key是Integer类型时推荐使用SparseArrayCompat()。
final SparseArrayCompat<LoaderInfo> mLoaders = new SparseArrayCompat<LoaderInfo>();
// These are previously run loaders. This list is maintained internally
// to avoid destroying a loader while an application is still using it.
// It allows an application to restart a loader, but continue using its
// previously run loader until the new loader's data is available.
//这些是以前运行的loader。这个列表在内部维护,避免应用程序正在使用时销毁Loader。允许应用程序重新开启一个loader,但是会继续使用之前的loader直到新的loader加载的数据可用。
//待用的Loader集合
final SparseArrayCompat<LoaderInfo> mInactiveLoaders = new SparseArrayCompat<LoaderInfo>();
final String mWho;
boolean mStarted;
//正在保留中
boolean mRetaining;
//'保留'是否开始
boolean mRetainingStarted;
//表示loader正在创建中,createAndInstallLoader方法中体现。
boolean mCreatingLoader;
FragmentHostCallback mHost;
final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
Loader.OnLoadCanceledListener<Object> {
//创建时指定的loader的ID
final int mId;
//创建时指定的传递参数
final Bundle mArgs;
//LoaderManager的回调
LoaderManager.LoaderCallbacks<Object> mCallbacks;
//这就是Loader加载器。
Loader<Object> mLoader;
boolean mHaveData;
//是否已经分发数据。调用完onLoadFinished方法,赋值true。
boolean mDeliveredData;
Object mData;
@SuppressWarnings("hiding")
boolean mStarted;
@SuppressWarnings("hiding")
boolean mRetaining;
@SuppressWarnings("hiding")
boolean mRetainingStarted;
boolean mReportNextStart;
//表示Loader正在销毁
boolean mDestroyed;
// 是否已经监听Loader,主要监听两个回调方法:
//OnLoadCompleteListener OnLoadCanceledListener
boolean mListenerRegistered;
//正在等待的Loader
LoaderInfo mPendingLoader;
public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {
mId = id;
mArgs = args;
mCallbacks = callbacks;
}
void start() {
//如果处于保留状态,或者保留开始状态,表示loader已经被开启直接退出方法,其实并没有做什么操作。
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;
}
//如果loader已经被启动,不在重新启动
if (mStarted) {
// If loader already started, don't restart.
return;
}
mStarted = true;
if (DEBUG) Log.v(TAG, " Starting: " + this);
//在这里又判断了一次。如果mLoader为null,则调用你返回的Loader实例。
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) {
//注册已经Loader加载完成数据的监听
mLoader.registerListener(mId, this);
//注册已经取消加载数据的监听
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
//最后调用Loader的startLoading方法,表示已经开始加载数据了。
mLoader.startLoading();
}
}
//此方法是保留的意思。其实做的只有记录状态。
void retain() {
if (DEBUG) Log.v(TAG, " Retaining: " + this);
mRetaining = true;
mRetainingStarted = mStarted;
mStarted = false;
mCallbacks = null;
}
//这个加载器已经保留在开启的状态,但是不保证不在启动结束,所以使其停止。
void finishRetain() {
if (mRetaining) {
if (DEBUG) Log.v(TAG, " Finished Retaining: " + this);
mRetaining = false;
if (mStarted != mRetainingStarted) {
if (!mStarted) {
// This loader was retained in a started state, but
// at the end of retaining everything our owner is
// no longer started... so make it stop.
stop();
}
}
}
//这个Loader已经保留了数据,要么通过更改全部的配置,无论最后一个数据集是从停止到重新启动后,而现在在完成保留时,我们发现仍然可以开始,有我们的数据,客户端有个新的回调,所以我们要现在提供新的数据。
if (mStarted && mHaveData && !mReportNextStart) {
// This loader has retained its data, either completely across
// a configuration change or just whatever the last data set
// was after being restarted from a stop, and now at the point of
// finishing the retain we find we remain started, have
// our data, and the owner has a new callback... so
// let's deliver the data now.
callOnLoadFinished(mLoader, mData);
}
}
void reportStart() {
if (mStarted) {
if (mReportNextStart) {
mReportNextStart = false;
if (mHaveData && !mRetaining) {
callOnLoadFinished(mLoader, mData);
}
}
}
}
void stop() {
if (DEBUG) Log.v(TAG, " Stopping: " + this);
//首先对mStarte状态赋值。
mStarted = false;
//如果不保留
if (!mRetaining) {
if (mLoader != null && mListenerRegistered) {
// Let the loader know we're done with it
//修改禁停状态,然后取消监听,最后调用stopLoading方法。
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
mLoader.stopLoading();
}
}
}
//会根据Loader类的返回值决定是否调用onLoadCanceled方法。
boolean cancel() {
if (DEBUG) Log.v(TAG, " Canceling: " + this);
if (mStarted && mLoader != null && mListenerRegistered) {
final boolean cancelLoadResult = mLoader.cancelLoad();
if (!cancelLoadResult) {
onLoadCanceled(mLoader);
}
return cancelLoadResult;
}
return false;
}
void destroy() {
if (DEBUG) Log.v(TAG, " Destroying: " + this);
//设置状态。表示正在销毁。
mDestroyed = true;
boolean needReset = mDeliveredData;
mDeliveredData = false;
//如果这个字段都还存在,会在销毁之前调用onLoaderReset,让你有时间去释放你的数据资源。
if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
if (DEBUG) Log.v(TAG, " Resetting: " + this);
String lastBecause = null;
if (mHost != null) {
lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
}
try {
mCallbacks.onLoaderReset(mLoader);
} finally {
if (mHost != null) {
mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
}
//释放资源
mCallbacks = null;
mData = null;
mHaveData = false;
if (mLoader != null) {
//重置状态,并且移除监听器。
if (mListenerRegistered) {
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
}
//调用loader的reset(),来重置Loader内部状态,reset方法会调用onReset方法。在这个方法中应该释放掉你的所有资源。
mLoader.reset();
}
//如果有等待的Loader,也给释放掉。
if (mPendingLoader != null) {
mPendingLoader.destroy();
}
}
//如果有就等待的Loader,就切换Loader。如果没有就什么都不做。
@Override
public void onLoadCanceled(Loader<Object> loader) {
if (DEBUG) Log.v(TAG, "onLoadCanceled: " + this);
//如果正在销毁中,就不需要在取消了。
if (mDestroyed) {
if (DEBUG) Log.v(TAG, " Ignoring load canceled -- destroyed");
return;
}
//如果Loader不是来自当前活动的Loader,我们不做处理。
if (mLoaders.get(mId) != this) {
// This cancellation message is not coming from the current active loader.
// We don't care about it.
if (DEBUG) Log.v(TAG, " Ignoring load canceled -- not active");
return;
}
//判断是否有新的Loader正在等待。如果有切换Loader,旧的loader销毁掉,新的Loader加入到集合中。
LoaderInfo pending = mPendingLoader;
if (pending != null) {
//有一个新的Loader请求正在等待,我们需要在新的Loader在starting(开始)之前取消或者完成。所以现在时机到了,应该切换到新的Loader。
// There is a new request pending and we were just
// waiting for the old one to cancel or complete before starting
// it. So now it is time, switch over to the new loader.
if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending);
mPendingLoader = null;
mLoaders.put(mId, null);
destroy();
installLoader(pending);
}
}
@Override
public void onLoadComplete(Loader<Object> loader, Object data) {
if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);
//如果Loader正在销毁,结束此方法。
if (mDestroyed) {
if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed");
return;
}
//校验Loader实例,如果不是从当前活动的Loader提交的数据,不用理会它。
if (mLoaders.get(mId) != this) {
// This data is not coming from the current active loader.
// We don't care about it.
if (DEBUG) Log.v(TAG, " Ignoring load complete -- not active");
return;
}
//如果有在等待的Loader,在旧的Loader加载完数据之后,切换Loader。旧的mPendingLoader设置成当前的Loader,让后销毁掉。
LoaderInfo pending = mPendingLoader;
if (pending != null) {
// There is a new request pending and we were just
// waiting for the old one to complete before starting
// it. So now it is time, switch over to the new loader.
//有一个新的请求正在等待,我们只是在开始之前等待旧的请求完成。 所以现在是时候了,切换到新的加载器。
if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending);
mPendingLoader = null;
mLoaders.put(mId, null);
destroy();
installLoader(pending);
return;
}
// Notify of the new data so the app can switch out the old data before
// we try to destroy it.
//通知新数据,一般app能销毁旧数据之前能即使切换数据。
//把加载完成的数据,通过回调返回给你。
if (mData != data || !mHaveData) {
mData = data;
mHaveData = true;
if (mStarted) {
//通过此方法,把最后的结果数据传递给你。并标记正在分发结果。
callOnLoadFinished(loader, data);
}
}
//if (DEBUG) Log.v(TAG, " onLoadFinished returned: " + this);
// We have now given the application the new loader with its
// loaded data, so it should have stopped using the previous
// loader. If there is a previous loader on the inactive list,
// clean it up.
//现在我们已经给应用程序加载了带有加载数据的新加载器,所以它应该停止使用前面的加载器。 如果在非活动列表中有前一个加载器,请清理它。
//获取到待用的Loader,如果待用的Loader不是null,也不是当前使用的LoaderInfo,则表示不在需要此LoaderInfo,销毁掉,并移出Loader待用集合。
//发送完数据立即把状态置false。
LoaderInfo info = mInactiveLoaders.get(mId);
if (info != null && info != this) {
info.mDeliveredData = false;
info.destroy();
mInactiveLoaders.remove(mId);
}
if (mHost != null && !hasRunningLoaders()) {
mHost.mFragmentManager.startPendingDeferredFragments();
}
}
//通过此方法,把最后的结果数据传递给你。并标记已经分发数据。
void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
if (mHost != null) {
lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
mCallbacks.onLoadFinished(loader, data);
} finally {
if (mHost != null) {
mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(64);
sb.append("LoaderInfo{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" #");
sb.append(mId);
sb.append(" : ");
DebugUtils.buildShortClassTag(mLoader, sb);
sb.append("}}");
return sb.toString();
}
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
writer.print(prefix); writer.print("mId="); writer.print(mId);
writer.print(" mArgs="); writer.println(mArgs);
writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks);
writer.print(prefix); writer.print("mLoader="); writer.println(mLoader);
if (mLoader != null) {
mLoader.dump(prefix + " ", fd, writer, args);
}
if (mHaveData || mDeliveredData) {
writer.print(prefix); writer.print("mHaveData="); writer.print(mHaveData);
writer.print(" mDeliveredData="); writer.println(mDeliveredData);
writer.print(prefix); writer.print("mData="); writer.println(mData);
}
writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
writer.print(" mReportNextStart="); writer.print(mReportNextStart);
writer.print(" mDestroyed="); writer.println(mDestroyed);
writer.print(prefix); writer.print("mRetaining="); writer.print(mRetaining);
writer.print(" mRetainingStarted="); writer.print(mRetainingStarted);
writer.print(" mListenerRegistered="); writer.println(mListenerRegistered);
if (mPendingLoader != null) {
writer.print(prefix); writer.println("Pending Loader ");
writer.print(mPendingLoader); writer.println(":");
mPendingLoader.dump(prefix + " ", fd, writer, args);
}
}
}
LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) {
mWho = who;
mHost = host;
mStarted = started;
}
void updateHostController(FragmentHostCallback host) {
mHost = host;
}
/**
初始化LoaderInfo实例,然后把用户创建的Loader赋值到LoaderInfo的mLoader中,最后返回LoaderInfo实例。
/
private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args, callback);
Loader<Object> loader = callback.onCreateLoader(id, args);
info.mLoader = loader;
return info;
}
private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
//表示Loader正在创建
mCreatingLoader = true;
LoaderInfo info = createLoader(id, args, callback);
installLoader(info);
return info;
} finally {
//表示loader已经创建完成。
mCreatingLoader = false;
}
}
//把刚刚创建的LoaderInfo存放在集合中。
//如果当前状态是已经开启状态,则调用LoaderInfo中的。start方法
//该活动将要开启所有存在的Loader的onStart方法,因此必须确保activity的生命周期的那个点已经调用过了。
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 activity's
// life cycle
info.start();
}
}
/**
* Call to initialize a particular ID with a Loader. If this ID already
* has a Loader associated with it, it is left unchanged and any previous
* callbacks replaced with the newly provided ones. If there is not currently
* a Loader for the ID, a new one is created and started.
*
* <p>This function should generally be used when a component is initializing,
* to ensure that a Loader it relies on is created. This allows it to re-use
* an existing Loader's data if there already is one, so that for example
* when an {@link Activity} is re-created after a configuration change it
* does not need to re-create its loaders.
*
* <p>Note that in the case where an existing Loader is re-used, the
* <var>args</var> given here <em>will be ignored</em> because you will
* continue using the previous Loader.
*
* @param id A unique (to this LoaderManager instance) identifier under
* which to manage the new Loader.
* @param args Optional arguments that will be propagated to
* {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
* @param callback Interface implementing management of this Loader. Required.
* Its onCreateLoader() method will be called while inside of the function to
* instantiate the Loader object.
*/
@Override
@SuppressWarnings("unchecked")
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
//如果Loade正在创建则抛异常。正在创建是在createAndInstallLoader方法中体现。
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
//根据传入的id在正在活动中的LoaderInfo集合中查找指定id的LoaderInfo。
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
//如果找到指定的LoaderInfo则复用以前的LoaderInfo。并重新指定回调方法。
//如果LoaderInfo不存在,则创建一个新的LoaderInfo。
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;
}
//如果LoaderInfo中存在数据,并在启动状态下,则开始分发数据。
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;
}
/**
* Call to re-create the Loader associated with a particular ID. If there
* is currently a Loader associated with this ID, it will be
* canceled/stopped/destroyed as appropriate. A new Loader with the given
* arguments will be created and its data delivered to you once available.
*
* <p>This function does some throttling of Loaders. If too many Loaders
* have been created for the given ID but not yet generated their data,
* new calls to this function will create and return a new Loader but not
* actually start it until some previous loaders have completed.
*
* <p>After calling this function, any previous Loaders associated with
* this ID will be considered invalid, and you will receive no further
* data updates from them.
*
* @param id A unique (to this LoaderManager instance) identifier under
* which to manage the new Loader.
* @param args Optional arguments that will be propagated to
* {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
* @param callback Interface implementing management of this Loader. Required.
* Its onCreateLoader() method will be called while inside of the function to
* instantiate the Loader object.
*/
@Override
@SuppressWarnings("unchecked")
public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
//如果loader正在创建中,则抛出异常。
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
//根据传入的id,到集合中去拿LoaderInfo,
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args);
//如果取出的LoaderInfo不存在,那就简单了,在方法的末尾,创建一个新的LoaderInfo并返回。
if (info != null) {
//获取不活动的LoaderInfo
LoaderInfo inactive = mInactiveLoaders.get(id);
//不活跃的Loader如果是空,则loader调用abandon方法,并把loader放入不活跃的集合。
if (inactive != null) {
//查看Loader是否有数据。 销毁不活跃的loader。则loader调用abandon方法,表示已经被放弃,最后把指定id的loader放入不活跃的集合中。
if (info.mHaveData) {
//如果有数据。那么有可能正在调用onLoadComplete方法,还没有销毁最后一个不活跃的loader。那么现在来销毁它。
// This loader now has data... we are probably being
// called from within onLoadComplete, where we haven't
// yet destroyed the last inactive loader. So just do
// that now.
if (DEBUG) Log.v(TAG, " Removing last inactive loader: " + info);
inactive.mDeliveredData = false;
inactive.destroy();
info.mLoader.abandon();
mInactiveLoaders.put(id, info);
} else {
//info中没有要发送的数据。
//我们已经有了一个不活动的加载器,这个ID正在等待! 尝试取消; 如果这返回true,那么任务仍在运行,我们还有更多的工作要做。
// We already have an inactive loader for this ID that we are
// waiting for! Try to cancel; if this returns true then the task is still
// running and we have more work to do.
//loader没有在运行
if (!info.cancel()) {
//当前的Loader还没有启动或者被成功取消,我们没有理由保留它。 删除它,下面将创建一个新的LoaderInfo。
// The current Loader has not been started or was successfully canceled,
// we thus have no reason to keep it around. Remove it and a new
// LoaderInfo will be created below.
if (DEBUG) Log.v(TAG, " Current loader is stopped; replacing");
mLoaders.put(id, null);
info.destroy();
} else {
//cancel返回的是true,表示loader仍然在运行。
//现在我们有三个活动的装载机...一旦其他装载机完成,我们将排队这个请求进行处理。
// Now we have three active loaders... we'll queue
// up this request to be processed once one of the other loaders
// finishes.
if (DEBUG) Log.v(TAG,
" Current loader is running; configuring pending loader");
//如果有等待的laoder,销毁它
if (info.mPendingLoader != null) {
if (DEBUG) Log.v(TAG, " Removing pending loader: " + info.mPendingLoader);
info.mPendingLoader.destroy();
info.mPendingLoader = null;
}
//为loader创建一个等待的loader。
if (DEBUG) Log.v(TAG, " Enqueuing as new pending loader");
info.mPendingLoader = createLoader(id, args,
(LoaderManager.LoaderCallbacks<Object>)callback);
return (Loader<D>)info.mPendingLoader.mLoader;
}
}
} else {
如果这个LoaderInfo是null,把loaderInfo放入mInactiveLoaders集合中,
//跟踪这个加载器的前一个实例,以便在新加载完成时我们可以销毁它。
// Keep track of the previous instance of this loader so we can destroy
// it when the new one completes.
if (DEBUG) Log.v(TAG, " Making last loader inactive: " + info);
//调用Loader中的方法,表示要放弃此Loader。
info.mLoader.abandon();
//把指定id的Info存入不活跃的Loader集合中。
mInactiveLoaders.put(id, info);
}
}
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
return (Loader<D>)info.mLoader;
}
/**
* Rip down, tear apart, shred to pieces a current Loader ID. After returning
* from this function, any Loader objects associated with this ID are
* destroyed. Any data associated with them is destroyed. You better not
* be using it when you do this.
* @param id Identifier of the Loader to be destroyed.
*/
@Override
public void destroyLoader(int id) {
//loader正在创建是不能被销毁的。
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id);
//从活动的laoder中删除。然后销毁。
int idx = mLoaders.indexOfKey(id);
if (idx >= 0) {
LoaderInfo info = mLoaders.valueAt(idx);
mLoaders.removeAt(idx);
info.destroy();
}
//从不活动的loader中删除,并销毁。
idx = mInactiveLoaders.indexOfKey(id);
if (idx >= 0) {
LoaderInfo info = mInactiveLoaders.valueAt(idx);
mInactiveLoaders.removeAt(idx);
info.destroy();
}
if (mHost != null && !hasRunningLoaders()) {
mHost.mFragmentManager.startPendingDeferredFragments();
}
}
/**
* Return the most recent Loader object associated with the
* given ID.
*/
@Override
@SuppressWarnings("unchecked")
public <D> Loader<D> getLoader(int id) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
//根据id获取loader。
LoaderInfo loaderInfo = mLoaders.get(id);
if (loaderInfo != null) {
//如果指定id的loader有等待的loader,则返回等待的loader。如果没有等待的loader,则返回当前的loader。
if (loaderInfo.mPendingLoader != null) {
return (Loader<D>)loaderInfo.mPendingLoader.mLoader;
}
return (Loader<D>)loaderInfo.mLoader;
}
return null;
}
//这个方法会启动所有正在活动集合的loader。最后放入的最先执行。LoaderManager的mStarted变true。
void doStart() {
if (DEBUG) Log.v(TAG, "Starting in " + this);
if (mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Log.w(TAG, "Called doStart when already started: " + this, e);
return;
}
mStarted = true;
//调用子类以便启动加载程序让现有的加载程序知道我们希望在加载完成时收到通知
// Call out to sub classes so they can start their loaders
// Let the existing loaders know that we want to be notified when a load is complete
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).start();
}
}
//停止所有活动中的loader。LoaderManager的mStarted为false。
void doStop() {
if (DEBUG) Log.v(TAG, "Stopping in " + this);
if (!mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Log.w(TAG, "Called doStop when not started: " + this, e);
return;
}
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).stop();
}
mStarted = false;
}
//mStarted必须处于启动的状态。然后改变其状态,并执行所有正在活动的loader的retain方法。
void doRetain() {
if (DEBUG) Log.v(TAG, "Retaining in " + this);
if (!mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Log.w(TAG, "Called doRetain when not started: " + this, e);
return;
}
mRetaining = true;
mStarted = false;
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).retain();
}
}
//mRetaining必须为true。改变其状态,执行所有活动的loader的finishRetain方法。
void finishRetain() {
if (mRetaining) {
if (DEBUG) Log.v(TAG, "Finished Retaining in " + this);
mRetaining = false;
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).finishRetain();
}
}
}
//当Fragment执行到onDestroyView生命周期时,对自己的LoaderManager发出请求:即使现在有数据也不要进行上报,等我重做再到onStart生命周期时再给我。
void doReportNextStart() {
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).mReportNextStart = true;
}
}
//如果Fragment上一次在销毁并重做,而且数据有效的话会在这里主动上报数据,最终走到callback的onLoadFinished中。
void doReportStart() {
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).reportStart();
}
}
//这里有个参数mRetaining,如果mRetaining是否保留,如果为false。表示不保留,那么活动的loader都会被彻底销毁;如果mRetaining是true,则表示需要保留,那么将跳过销毁正在活动的loader。
//不活跃的loader会被无情的销毁。
void doDestroy() {
if (!mRetaining) {
if (DEBUG) Log.v(TAG, "Destroying Active in " + this);
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).destroy();
}
mLoaders.clear();
}
if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this);
for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
mInactiveLoaders.valueAt(i).destroy();
}
mInactiveLoaders.clear();
mHost = null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("LoaderManager{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" in ");
DebugUtils.buildShortClassTag(mHost, sb);
sb.append("}}");
return sb.toString();
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
if (mLoaders.size() > 0) {
writer.print(prefix); writer.println("Active Loaders:");
String innerPrefix = prefix + " ";
for (int i=0; i < mLoaders.size(); i++) {
LoaderInfo li = mLoaders.valueAt(i);
writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i));
writer.print(": "); writer.println(li.toString());
li.dump(innerPrefix, fd, writer, args);
}
}
if (mInactiveLoaders.size() > 0) {
writer.print(prefix); writer.println("Inactive Loaders:");
String innerPrefix = prefix + " ";
for (int i=0; i < mInactiveLoaders.size(); i++) {
LoaderInfo li = mInactiveLoaders.valueAt(i);
writer.print(prefix); writer.print(" #"); writer.print(mInactiveLoaders.keyAt(i));
writer.print(": "); writer.println(li.toString());
li.dump(innerPrefix, fd, writer, args);
}
}
}
//判断的是loader是否已经看起,但是没有分发消息。
@Override
public boolean hasRunningLoaders() {
boolean loadersRunning = false;
final int count = mLoaders.size();
for (int i = 0; i < count; i++) {
final LoaderInfo li = mLoaders.valueAt(i);
loadersRunning |= li.mStarted && !li.mDeliveredData;
}
return loadersRunning;
}
}