标签:android android开发 loadermanager
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;}
LoaderInfo声明了Loader.OnLoadCompleteListener接口,并且保存了一个Loader的几乎所有信息和状态。
LoaderInfo的构造函数
public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {mId = id;mArgs = args;mCallbacks = callbacks;}
createAndInstallLoader
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;}
通过调用callback的onCreateLoader接口创建Loader。这样一个描述Loader的LoaderInfo就被成功创建了。完成了创建后,接下来是安装。
installLoader
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 cycleinfo.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);mListenerRegistered = true;}mLoader.startLoading();}}
Loader的startLoading()
public final void startLoading() {mStarted = true;mReset = false;mAbandoned = false;onStartLoading();}
会启动Loader的onStartLoading,如果是复写的Loader或者AsyncTaskLoader,就是执行到了这里,是Loader在构造后执行的第一道工序。
在LoaderInfo中给Loader注册了回调,回调就是LoaderInfo本身。下边以AsyncTaskLoader为例进行分析。
AsyncTaskLoader继承于Loader,同时其内部完成了一个AsyncTask。AsyncTaskLoader的抽象接口
public abstract D loadInBackground();
其实就是运行在其内部的AsyncTask中的doInBackground。
PS: 继承于AsyncTaskLoader的Loader不会在构造后自动启动,需要覆写
onStartLoading中执行forceLoad,此Loader才会在onStartLoading的生命周期时正常启动。
在其内部的AsyncTask完成后会在onPostExecute中调用AsyncTaskLoader的dispatchOnLoadComplete
void dispatchOnLoadComplete(LoadTask task, D data) {if (mTask != task) {if (DEBUG) Slog.v(TAG, "Load complete of old task, trying to cancel");dispatchOnCancelled(task, data);} else {if (isAbandoned()) {// This cursor has been abandoned; just cancel the new data.onCanceled(data);} else {commitContentChanged();mLastLoadCompleteTime = SystemClock.uptimeMillis();mTask = null;if (DEBUG) Slog.v(TAG, "Delivering result");deliverResult(data);}}}
isAbandoned是Loader的方法,通过主动调用Loader的abandon()方法可以放弃这个Loader的执行结果,如果此Loader已经被放弃,那么调用
public void onCanceled(D data)
处理被去掉的数据,AsyncTaskLoader中没有做任何处理,留给继承者自行决定是否处理
排除以上两种异常情况,正常时会调用Loader的deliverResult处理数据结果。
public void deliverResult(D data) {if (mListener != null) {mListener.onLoadComplete(this, data);}}
之前分析过的LoaderInfo为自己的Loader注册了监听器,实现是自己,这下子数据就传递回去了:
@Override public void onLoadComplete(Loader<Object> loader, Object data) {if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);if (mDestroyed) {if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed");return;}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;}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.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.LoaderInfo info = mInactiveLoaders.get(mId);if (info != null && info != this) {info.mDeliveredData = false;info.destroy();mInactiveLoaders.remove(mId);}if (mActivity != null && !hasRunningLoaders()) {mActivity.mFragments.startPendingDeferredFragments();}}
destroy()进行过销毁,则不处理任何事情callOnLoadFinished对数据进行处理,这里调用了回调函数callback中的onLoadFinishedActivity和Fragment都拥有getLoaderManager的方法,其实Fragment的getLoaderManager去获取的就是Activity所管理的众多LoaderManager之一。
先来看一下Activity的getLoaderManager方法:
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {if (mAllLoaderManagers == null) {mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();}LoaderManagerImpl lm = mAllLoaderManagers.get(who);if (lm == null) {if (create) {lm = new LoaderManagerImpl(who, this, started);mAllLoaderManagers.put(who, lm);}} else {lm.updateActivity(this);}return lm;}
mAllLoaderManagers保存着一个Activity所拥有的所有LoaderManager,其key为String类型的who变量。若从Activity调用getLoaderManager,那么所得LoaderManager的who标签为(root):
public LoaderManager getLoaderManager() {if (mLoaderManager != null) {return mLoaderManager;}mCheckedForLoaderManager = true;mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);return mLoaderManager;}
若从Fragment中使用getLoaderManager,则所得LoaderManager的who标签会根据Fragment的层级不同而不同,在Activity中处于最顶级的Fragment的who标签为:
android:fragment:X
X为序号。
而属于Fragment的Fragment所活的的LoaderManager who标签就成为了:
android:fragment:X:Y
甚至更大的深度。
在开篇分析的时候分析过LoaderManager内部保存了一个mStarted状态,很多操作会根据这个状态做不同处理。通过上边的分析也能看出,Fragment中获取LoaderManager最终是通过Activity获取的,在LoaderManager构造时,就将一个状态量mLoadersStarted传递了进去,这个状态量交给LoaderManager自行管理。
而无论是Fragment还是Activity,都有mLoadersStarted这样一个状态量,在onStart生命周期后为true,onStop后为false。所以在onStart生命周期后做initLoader操作就会使Loader一经初始化就开始运行了。
Fragment和Activity能够对LoaderManager产生影响的生命周期是一样的。
系统在onStart阶段会获取LoaderManager,如果成功获取,则调用LoaderManager的doStart(),这里需要特别说明的是,虽然所有LoaderManager都是保存在Activity中,但是在Activity的onStart生命周期其也只是会获取属于自己的(root)标签LoaderManager,而并不是将所有保存在mAllLoaderManagers里的Manager全部遍历一遍。
处于onStop生命周期,但是系统内部是通过performStop调用的。在这里,同样会获取属于自己的LoaderManager,如果Activity是因为配置改变出发的onStop(旋转屏幕),则调用LoaderManager的doRetain()接口,如果不是,就调用LoaderManager的doStop()接口。
调用LoaderManager的doDestroy()接口销毁LoaderManager。
因为LoaderManager与Fragment/Activity的生命周期紧密相连,所以想要用好LoaderManager就必须了解其自身的生命周期,这样就能把握数据的完整变化规律了。
正常的从出生到销毁:
doStart() -> doReportStart() -> doStop() -> doDestroy()
Activity配置发生变化:
doStart() -> doRetain() -> finishRetain() -> doReportStart() -> doStart() -> doStop() -> doDestroy()
Fragment在onDestroyView()之后还会执行LoaderManager的doReportNextStart(), 即:
doStart() -> doRetain() -> doReportNextStart() -> finishRetain() -> doReportStart() -> doStart() -> doStop() -> doDestroy()
doStart()会将LoaderManager中保存的所有Loader都启动。最终是运行每一个Loader的onStartLoading()方法。只要是通过initLoader使用过的Loader都会记录在LoaderManager的mLoaders中,那么问题来了:
怎样在Fragment/Activity不销毁的前提下从LoaderManager中移除某个使用过的Loader呢?
答案就是使用LoaderManager的接口去除指定ID的Loader:
public void destroyLoader(int id)
这样就能在mLoaders中移除掉了,下次onStart的时候就没有这个Loader什么事了。
doReportStart()。如果Fragment上一次在销毁并重做,而且数据有效的话会在这里主动上报数据,最终走到callback的onLoadFinished中。doStop()会停止mLoaders保存的所有Loader。最终是运行每一个Loader的onStopLoading()方法。doDestroy()会清空所有有效和无效Loader,LoaderManager中不再存在任何Loader。doRetain()会将LoaderManager的mRetaining状态置位true,并且保存retain时LoaderInfo的mStarted状态finishRetain()如果之前所保存的mStarted与现在的不一样而且新的状态是停止的话,就停止掉这个Loader。否则若有数据并且不是要下次再上报(没有call
doReportNextStart)的话就上报给callback的onLoadFinished。doReportNextStart(),根据第6条,已经能够理解了。当Fragment执行到onDestroyView生命周期时,对自己的LoaderManager发出请求:即使现在有数据也不要进行上报,等我重做再到onStart生命周期时再给我。在熟知了LoaderManager的梗概之后最后分析restartLoader就能够更好理解了:
public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback)
Android应用开发:LoaderManager在Activity/Fragment中的使用分析
标签:android android开发 loadermanager
原文地址:http://blog.csdn.net/airk000/article/details/40181189