Loader是Android3.0之后推出的一個異步加載類,他可以方便我們在Activity和Fragment中異步加載數(shù)據(jù)废酷,Loader有一下特點
- 可用于每個Activity和Fragment澈蟆。
- 支持異步加載數(shù)據(jù)。
- 監(jiān)控其數(shù)據(jù)源并在內容變化時傳遞新結果寥闪。
- 在某一配置更改后重建加載器時疲憋,會自動重新連接上一個加載器的游標敛纲。 因此翰绊,它們無需重新查詢其數(shù)據(jù)监嗜。
Loader的使用
- initLoader()保證一個加載器被初始化并激活.它具有兩種可能的結果:
- 如果ID所指的加載器已經存在桐猬,那么這個加載器將被重用.
- 如果加載器不存在,initLoader()就觸發(fā)LoaderManager.LoaderCallbacks的方法onCreateLoader().這是你實例化并返回一個新加載器的地方.
- 想要丟棄舊的數(shù)據(jù),使用restartLoader()
示例代碼
//示例代碼
//1:id 2:可選參數(shù) 3:回調函數(shù)
getLoaderManager().initLoader(1, null, mCallback);
getLoaderManager().restartLoader(1, null, mCallback);
getLoaderManager().destroyLoader(1);
LoaderManager.LoaderCallbacks<Object> mCallback = new LoaderManager.LoaderCallbacks<Object>() {
@Override
public Loader<Object> onCreateLoader(int id, Bundle args) {
Log.e("MainActivity", "onCreateLoader---" + id);
Loader<Object> loader = new Loader<>(MainActivity.this);
return loader;
}
@Override
public void onLoadFinished(Loader<Object> loader, Object data) {
Log.e("MainActivity", "onLoadFinished");
}
@Override
public void onLoaderReset(Loader<Object> loader) {
Log.e("MainActivity", "onLoaderReset");
}
};
ps:當onCreateLoader的返回值為null的時候厨钻,onCreateLoader會被回調兩次,其中第二次是在Activity的onStart 方法中回調的
getLoaderManager()獲取到的LoaderManager的實現(xiàn)類是LoaderManagerImpl
LoaderManagerImpl的initLoader方法:
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 (info == null) {
// Loader doesn't already exist; create.
10 info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
} else {
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;
}
initLoader()會先通過mLoaders.get(id)來根據(jù)id獲取LoaderInfo對象夯膀。如果Activity或Fragment是第一次調用initLoader()苍蔬,則獲取到的LoaderInfo對象為null诱建。
如果LoaderInfo對象為null银室,則接著調用createAndInstallLoader()方法(第十行)
下面是createAndInstallLoader()方法的實現(xiàn)
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;
}
}
private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); //創(chuàng)建LoaderInfo對象
Loader<Object> loader = callback.onCreateLoader(id, args); //這里是第一調用onCreateLoader()來創(chuàng)建一個loader對象(可能為null)
info.mLoader = (Loader<Object>)loader;
return info;
}
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 這里如果initloader方法如果在onStart()之后,則在這里start第二次
info.start();
}
}
createAndInstallLoader會調用createLoader和installLoader
installLoader方法里面的注釋說
The activity will start all existing loaders in it's onStart(),
Activity的onStart()方法:
protected void onStart() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
mFragments.doLoaderStart();
getApplication().dispatchActivityStarted(this);
}
//mFragments.doLoaderStart()方法最終會調用到LoaderManager的doStart()方法
void doStart() {
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();
} //在這里會 start all existing loaders
}
在Activity的onStart()生命周期方法中,最終會調用到LoaderManagerImpl的doStart()方法,在doStart()方法中會有一個for循環(huán)苗桂,會把所有存在的Loader都調用一次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;
//這里createLoader方法里面第一次調用onCreateLoader()如果返回不為空,則不再調用第二次
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();
}
}
So:如果onCreateLoader返回為null告组,則onCreateLoader則會執(zhí)行兩次煤伟。
start方法中有一個非常重要的成員——mLoader(第一次調用onCreateLoader方法返回的Loader對象)
start方法最后會調用mLoader.startLoading();
代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("gj", "before");
getLoaderManager().initLoader(1, null, mCallback);
Log.e("gj", "after");
}
@Override
protected void onStart() {
Log.e("gj", "before_onStart");
super.onStart();
Log.e("gj", "after_onStart");
}
LoaderManager.LoaderCallbacks<Object> mCallback = new LoaderManager.LoaderCallbacks<Object>() {
@Override
public Loader<Object> onCreateLoader(int id, Bundle args) {
Log.e("gj", "onCreateLoader---" + id);
return null;
}
@Override
public void onLoadFinished(Loader<Object> loader, Object data) {
Log.e("gj", "onLoadFinished");
}
@Override
public void onLoaderReset(Loader<Object> loader) {
Log.e("gj", "onLoaderReset");
}
};
輸出日志
before_onCreate
onCreateLoader---1
after_onCreate
before_onStart
onCreateLoader---1
after_onStart
當在onStart()之后initLoader的代碼
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
Log.e("gj", "before_onStart");
super.onStart();
Log.e("gj", "after_onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.e("gj", "before_onResume");
getLoaderManager().initLoader(1, null, mCallback);
Log.e("gj", "after_onResume");
}
LoaderManager.LoaderCallbacks<Object> mCallback = new LoaderManager.LoaderCallbacks<Object>() {
@Override
public Loader<Object> onCreateLoader(int id, Bundle args) {
Log.e("gj", "onCreateLoader---" + id);
return null;
}
@Override
public void onLoadFinished(Loader<Object> loader, Object data) {
Log.e("gj", "onLoadFinished");
}
@Override
public void onLoaderReset(Loader<Object> loader) {
Log.e("gj", "onLoaderReset");
}
};
輸出日志:
before_onStart
after_onStart
before_onResume
onCreateLoader---1
onCreateLoader---1
after_onResume
到這里只分析到mLoader.startLoading(); 知道了為什么onCreateLoader返回為null的話他會被調用兩次
異步執(zhí)行的過程,接下來請看Android Loader源碼分析(二)