最近学习了LoaderManager的使用,整理一下。
写了一个小demo。
package com.example.test;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
@SuppressLint("NewApi")
public class TestLoaderManagerActivity extends Activity implements LoaderCallbacks<Cursor> {
LoaderManager mManager;
private final static int INIT_ID = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mManager = getLoaderManager();
mManager.initLoader(INIT_ID, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
return new ObjectCursorLoader(this);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if(cursor != null) {
cursor.close();
}
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {}
}
package com.example.test;
import android.annotation.SuppressLint;
import android.content.AsyncTaskLoader;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore.Images;
@SuppressLint("NewApi") public
class ObjectCursorLoader extends AsyncTaskLoader<Cursor> {
private Context mContext;
public ObjectCursorLoader(Context context) {
super(context);
mContext = context;
}
@Override
public Cursor loadInBackground() {
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = resolver.query(Images.Media.EXTERNAL_CONTENT_URI, null, null, null,
null);
return cursor;
}
@Override
public void deliverResult(Cursor data) {
super.deliverResult(data);
}
@Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
}
}
自定义实现AsyncTaskLoader<D>时除了必须实现doInbackground()方法之外, 必须实现onStartLoading方法,否则不会主动执行doInbackground() 方法。
下面看一下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;
}
----> 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;
}
}
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.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);
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
mLoader.startLoading();
}
}
这时会调用Loader.startLoading()方法,接下来进入到Loader.java类中。
public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
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() {
}
这时就十分清晰了,在Loader.java中onStartLoading() 方法什么也没有做,所以,不会继续往下执行。 因此,自定义实现Loader必须实现onStartLoading方法。