Loader以及LoaderManager是Android Framework中异步加载各种数据(不限于Cursor)的标准机制。
Loader是加载器,它完成实际的数据加载工作。LoaderManager是Loader的管理者,其管理着一个或多个Loader的生命周期。
LoaderManger有两个方法我们会经常用到:initLoader()方法和restartLoader()方法。
initLoader:通过调用LoaderManagr的initLoader()方法,可以创建一个Loader。
restartLoader:通过调用LoaderManager的restartLoader()方法,可以重启一个Loader。
destroyLoader:通过调用LoaderManager的destroyLoader()方法,可以销毁一个Loader,不过该方法不常用,因为LoaderManager在合适的时机下会自动销毁Loader。
LoaderManager.LoaderCallbacks:LoaderManager.LoaderCallbacks是LoaderManager中的内部接口,客户端与Loader的通信完全是事件机制,即客户端需要实现LoaderCallbacks中的各种回调方法,以响应Loader & LoaderManager触发的各种事件。客户端在调用LoaderManager的initLoader()或restartLoader()方法时,就需要客户端向这两个方法中传入一个LoaderCallbacks的实例。
LoaderCallbacks有三个回调方法需要实现:onCreateLoader()、onLoadFinished()以及onLoaderReset()。
onCreateLoader:我们要在onCreateLoader()方法内返回一个Loader的实例对象。很多情况下,我们需要查询ContentProvider里面的内容,那么我们就需要在onCreateLoader中返回一个CursorLoader的实例,CursorLoader继承自Loader。当然,如果CursorLoader不能满足我们的需求,我们可以自己编写自己的Loader然后在此onCreateLoader方法中返回。
onLoadFinished:当onCreateLoader中创建的Loader完成数据加载的时候,我们会在onLoadFinished回调函数中得到加载的数据。在此方法中,客户端可以得到数据并加以使用,在这之前,如果客户端已经保存了一份老的数据,那么我们需要释放对老数据的引用。
onLoaderReset:当之前创建的Loader被销毁(且该Loader向客户端发送过数据)的时候,就会触发onLoaderReset()回调方法,此时表明我们之前获取的数据被重置且处于无效状态了,所以客户端不应该再使用这份“过期”的无效的老数据,应该释放对该无效数据的引用。
Loader:Loader是具体的数据加载器,但是需要说明的是Loader类本身并不支持异步加载机制,所以当我们要编写自己的数据加载器的时候,我们不应该直接继承自Loader类,我们应该继承自AsyncTaskLoader类,AsyncTaskLoader支持异步加载机制,下面会对AsyncTaskLoader详细解释,此处不多说。Loader有许多public的方法,比如startLoading()、stopLoading()等,但是客户端不应该直接调用这些方法,这些方法是由LoaderManager调用的,如果客户端调用了这些public的方法,就很有可能导致Loader生命周期出现混乱,进而影响到LoaderManager对Loader的管理。
AsyncTaskLoader: AsyncTaskLoader继承自Loader,上面我们提到了Loader类本身没有异步加载数据的机制,但是AsyncTaskLoader具有异步加载的机制,这是因为AsyncTaskLoader内部使用了AsyncTask来进行异步数据加载,所以如果我们想实现自己的Loader,我们应该直接继承自AsyncTaskLoader类(或其子类),而非Loader类。AsyncTaskLoader中的loadInBackground()方法是抽象方法,所以AsyncTaskLoader是抽象类,其子类应该实现loadInBackground()方法,在该方法中应该实现具体的异步加载逻辑。总之,AsyncTaskLoader不会阻塞主线程。
下面一张图能反应出这几个类之间的关系:
Activity与Fragment是客户端,客户端通过LoaderManager的initLoader或restartLoader向LoaderManager发起获取数据的请求,LoaderManager内部会创建相应的Loader去加载数据,数据加载完毕后会触发LoaderCallbacks中的相应回调方法,通过这些回调方法,Loader可以得知相应事件的触发。