LoaderManager:
1. HONEYCOMB引入的新工具类, 可以和Activity或者Fragment相关联, 并且能够同时管理复数个loader, 最常用的就是CursorLoader这个类,当然了,欢迎自己定制loader.
内部定义了一个load操作的callback类: LoaderCallbacks:
- Loader onCreateLoader(int id, Bundle args), callback来提供了一个Loader. 赋予其独立的id, 以及任何其他的附加信息.
- void onLoadFinished(Loader loader, D data): 一个之前被create的loader在结束了自己的finish以后会调用此callback, 不过注意:Application一般来说是不允许在这个callback中进行fragmentTransaction的commit的, 因为这个callback可能会发生在Activity的state因为pasuse等原因save 了state之后,如果commit会破坏之前save的state和当前真实state的不一致性.
- onLoadFinished这个回调会保证在这个loader提供的上一批数据被释放前被调用, 因此在这个时机应该移除所有对上一批数据的应用, 但是也不用多此一举的在这一步自己做释放,因此loader会处理好的.
- loader会监视data的变化, 并且通过再次调用onLoadFinished来告知, 你自己不必监视. loader在得知app不再使用这批数据的时候会将其释放, 比如,如果data是一个cursor, 而你使用了cursorLoader,那么不必你自己来close(), 但是如果cursor被用到了CursorAdapter中,你用该用swapCursor这个函数来进行data的更新, 旧的cursor不会被close.
- onLoaderReset(Loader loader), 当一个之前create的loader被reset了, 导致了其data无效化, 那么在这个callback中就应该移除所有对之前data的引用.
LoaderManager本身的一些函数:
- initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks callback): 这个函数会初始化并且启动由LoaderCallback提供的Loader, 如果loader之前存在,那么就会创建一个新的,否则则会reuse之前的loader.
- 注意一点的是,有可能会有这样的情况发生, LoaderCallback的onLoadFinished的回调可能非常迅速,有可能在initLoader这个函数过程中就会被调用(有点奇怪是怎么插进去的,如果是队列这种形式的话,后来才发现是在该函数中主动调用)
- restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks callback): new或者restart一个loader,如果之前已经start了一个同样id的loader, 那么这个loader会被destroy,新的loader会被启动
- destroyLoader(int id): 如果被destroy的loadewr之前有通过onLoadFinished传递data, 那么它的onLoaderReset会被调用.
LoaderManagerImpl 实现类:
- 内部会维护一个parseArray mLoaders来保存当前活动的loader, loader在被start到被stop/restart之间都是active的.
- SparseArray mInactiveLoaders
- LoaderManagerImpl的构造函数接受一个who字符串, 以及一个activity, 还有一个boolean started代表Activity/fragment是否已经started.
initLoader的具体实现:
*如果当前正在create loader, mCreatingLoader, 那么会直接抛异常, 否则尝试根据id从当前active的mLoaders中取出相同id的loader, 得到对应的loaderInfo, 如果发现没有找到,那么就真正的调用createAndInstallLoader(..)函数来重新create并且运行一个loader.- 否则将LoaderInfo的mCallbacks替换为当前爱你initloader时输入的mCallbacks参数.
- 注意,如果这里发现该Loader已经有了data(mHaveData)并且LoaderManager是已经start的,那么会直接调用callOnLoadFinished这个callback,这也就是之前OnLoadFinished说将的可能在init过程中就有调用的情况
createAndInstallLoader:
- 会将mCreatingLoader设为true表明当前正在create loader.
- 调用createLoader(id, args, callback)会得到一个LoaderInfo,里面含有一个loader.
- 调用installLoader(info)将loader start起来.
- createLoader(…): 会根据传入的信息new一个LoaderInfo, 然后再使用LoaderCallback的onCreateLoader(id, args)得到一个loader对象并挂接在LoaderInfo的mLoader上.
- installLoader(LoaderInfo info): 很简单,将新建的LoaderInfo加入到mLoaders中,然后如果LoaderManager已经start了,那么会直接调用LoaderInfo的start.
LoaderInfo implements Loader.OnLoadCompleteListener,
Loader.OnLoadCanceledListener, 代表着一个Loader以及其相关信息,是LoaderManagerImpl直接管理的单位, 同时从其实现的Listener接口也可以看出来,也充当了callback的角色:- LoaderInfo的start会将所属的loader启动:
- LoaderInfo内部维护了一个mStarted来表示loader是否已经start, 如果已经start的,那么直接return(这里会考虑mRetaining和mRetainingStarted)
- 如果发现loader还不存在,那么会调用callback的onCreateLoader()来获取一个loader, 再做一次内部类的检测(如果发现Loader类是一个内部成员类,并且不是一个static的内部类,那么会抛异常,应该是为了确保不会因为loader类引起内存泄漏)
- 如果Loader还没有注册过Listener,那么就会把LoadeInfo注册为Loader的Listener和OnLoadCanceledListener.
- 最后调用Loader的startLoading().
- LoaderInfo的start会将所属的loader启动:
LoaderManagerImpl有一堆的doStart/Stop…函数,这是其所在的Activity/Fragment生命周期变化时会调用loaderManager的这些状态改变函数:
- doStart(): 显然是Activity/Fragment start时被调用的, 如果已经start了, 那么会抛异常,否mStarted = true, 必将内部所保存的所有active的LoaderInfo都start.
- doStop(): 如果就没有start过,那么stop会抛异常(这么严格应该是为了保证生命周期切换的严谨), 挨个将active的loaderInfo进行stop, 并mStarted =false
- doDestroy(): 将active和非active的所有Loader都进行destroy, 并且clear两个LoaderInfo的List.
- hasRunningLoaders(): 挨个遍历active的LoaderInfo, 看是否有已经start的Loader并且还没有deliverdata的loader.
- destroyLoader(int id): 如果当前正在mCreatingLoader, 那么会抛异常. 然后遍历active和非active的LoaderInfo,找到相同id的Loader进行destroy. 最后如果mActivity不是null并且当前也没有了正在running的loader(hasRunningLoaders()), 那么会通知mActivity的mFragments(其实是一个FragmentManagerImpl)进行startPendingDeferredFragments将还在队列中的Fragment操作全部执行完毕.
- restartLoader(…): 如果正在mCreatingLoader,那么抛异常, 尝试在active的loaderInfo中查找对应id的loaderInfo, 如果确实找到了,那么再继续在Inactive的LoaderInfo中查找id, 如果也找到了一个inactive的loaderInfo, 那么如果此Loader已经有了data(mHaveData), 那么其mDeliveredData设置为false代表还有data需要传递,对其进行destroy,然后loader调用abandon().最后将active的loaderInfo加入到inactive的loaderInfo列表中. 否则如果此inactive的loader没有要deliver的data, 那么可以直接将LoaderInfo进行destroy了.最后还是调用createAndInstallLoader(…)
LoaderInfo作为Loader的Listener, 也Override了几个函数:
- onLoadComplete(Loader loader, Object data): 如果LoaderInfo已经被Destroy了,那么就直接忽略这次回调,否则如果在active loaderInfo也找不到Id标识的Loader,那么也直接return, 如果发现当前的LoaderInfo还有pending的loaderInfo, 有pendingInfo代表我们一直在等待old的loader结束,这个时候就是重新开始pending 的loaderInfo的时候了, 会把当前的LoaderInfodestroy然后将pending的 loader运行起来,如果LoadeInfo保存的mData和传入的data不一样或者目前还没有data, 那么如果Loader已经被start,就要可以调用callOnLoadFinished了. 如果当前在inactiveLoaders中有相同id的loaderInfo,那么直接remove. 最后如果mActivity存在并且当前没有正在运行的Loader,那么会调用Activity的fragmemnt的startPendingDeferredFragments.
- onLoadCanceled(Loader loader): 如果已经被destroy或者active的loader中没有, 那么直接返回忽略, 如果有pending的loader正在等待,那么这就是启动该pending loader的时机.
LoaderInfo的destroy():
- 会把在Loader上注册的Listener全部去掉,并且调用Loader的reset, 如果发现还有Pending的Loader(一个LoaderInfo),那么也会destroy pending的loader. 如果有有效的Callback和Loader并且haveData也指定了needReset, 那么会调用callback的onLoadReset.