Android??????????Loader?????
???????????? ???????[ 2015/10/9 13:13:33 ] ????????????????? ???????
????public void onContentChanged() {
????if (mStarted) {
????forceLoad();
????} else {
????// This loader has been stopped?? so we don't want to load
????// new data right now... but keep track of it changing to
????// refresh later if we start again.
????mContentChanged = true;
????}
????}
????public void forceLoad() {
????onForceLoad();
????}
????/**
????* Subclasses must implement this to take care of requests to {@link #forceLoad()}.
????* This will always be called from the process's main thread.
????*/
????protected void onForceLoad() {
????}
?????????AsyncTaskLoader??????????????
????//???????? asynacTaskLoader ???? ???????????AsyncTask???????????runnabele???
????//????????d ???d??????????d???????????????????????????????????loader???cursor
????//??????????????????loader???list????
????final class LoadTask extends AsyncTask<Void?? Void?? D> implements Runnable {
????private final CountDownLatch mDone = new CountDownLatch(1);
????// Set to true to indicate that the task has been posted to a handler for
????// execution at a later time. Used to throttle updates.
????boolean waiting;
????/* Runs on a worker thread */
????@Override
????protected D doInBackground(Void... params) {
????if (DEBUG) Log.v(TAG?? this + " >>> doInBackground");
????try {
????//????????????????????????????onLoadInBackGround????
????D data = AsyncTaskLoader.this.onLoadInBackground();
????if (DEBUG) Log.v(TAG?? this + " <<< doInBackground");
????return data;
????} catch (OperationCanceledException ex) {
????if (!isCancelled()) {
????// onLoadInBackground threw a canceled exception spuriously.
????// This is problematic because it means that the LoaderManager did not
????// cancel the Loader itself and still expects to receive a result.
????// Additionally?? the Loader's own state will not have been updated to
????// reflect the fact that the task was being canceled.
????// So we treat this case as an unhandled exception.
????throw ex;
????}
????if (DEBUG) Log.v(TAG?? this + " <<< doInBackground (was canceled)"?? ex);
????return null;
????}
????}
????//???滹?к????? ???
????}
????//???????????2?????? ????????? ??task??????????????????????????????
????//?????????????????????????????????loader??????????????д?????????
????protected D onLoadInBackground() {
????return loadInBackground();
????}
????public abstract D loadInBackground();
????//???????? ?????????????仯????? ?????????????????????????laodtask
????//???????????? ???CursorLoader???????????loadInBackground??????
????@Override
????protected void onForceLoad() {
????super.onForceLoad();
????cancelLoad();
????mTask = new LoadTask();
????if (DEBUG) Log.v(TAG?? "Preparing load: mTask=" + mTask);
????executePendingTask();
????}
????????????? ???????????????????仯????? ???????????????????loader???????????????????????????????????????????????? ?????????updateUI?????????background?????????????????????onLoadFinished?????????
?????????????AsyncTaskLoader?????
????//?????asynctask???? ???????????????????? ????????????
????@Override
????protected void onPostExecute(D data) {
????if (DEBUG) Log.v(TAG?? this + " onPostExecute");
????try {
????AsyncTaskLoader.this.dispatchOnLoadComplete(this?? data);
????} finally {
????mDone.countDown();
????}
????}
????//?????????????????????26??-
????void dispatchOnLoadComplete(LoadTask task?? D data) {
????if (mTask != task) {
????if (DEBUG) Log.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) Log.v(TAG?? "Delivering result");
????deliverResult(data);
????}
????}
????}
????//?????????????????mListtenr????????
????public void deliverResult(D data) {
????if (mListener != null) {
????mListener.onLoadComplete(this?? data);
????}
????}
????????????Listener????Loader?????????
????OnLoadCompleteListener<D> mListener;
????public interface OnLoadCompleteListener<D> {
????/**
????* Called on the thread that created the Loader when the load is complete.
????*
????* @param loader the loader that completed the load
????* @param data the result of the load
????*/
????public void onLoadComplete(Loader<D> loader?? D data);
????}
????//?????????????
????public void registerListener(int id?? OnLoadCompleteListener<D> listener) {
????if (mListener != null) {
????throw new IllegalStateException("There is already a listener registered");
????}
????mListener = listener;
????mId = id;
????}
????????? ???????????? ???????????????registerlistener??????? ???????
????//???initLoader????????? ??????????????LoaderManger????
????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) {
????//?????????????30??
????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;
????}
????private LoaderInfo createAndInstallLoader(int id?? Bundle args??
????LoaderManager.LoaderCallbacks<Object> callback) {
????try {
????mCreatingLoader = true;
????LoaderInfo info = createLoader(id?? args?? callback);
????//?????????43??
????installLoader(info);
????return info;
????} finally {
????mCreatingLoader = false;
????}
????}
????void installLoader(LoaderInfo info) {
????mLoaders.put(info.mId?? info);
????if (mStarted) {
????//?????51??
????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?????????????????????this ???loaderInfo????? ??????????loadermanger?????????? ??????????
????//?????????? ??asynctask????????????mLoader???onLoadComplete???? ???????????loaderInfo???????????????????????91??
????mLoader.registerListener(mId?? this);
????mLoader.registerOnLoadCanceledListener(this);
????mListenerRegistered = true;
????}
????mLoader.startLoading();
????}
????}
????@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) {
????//???????? ????149??
????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 (mHost != null && !hasRunningLoaders()) {
????mHost.mFragmentManager.startPendingDeferredFragments();
????}
????}
????void callOnLoadFinished(Loader<Object> loader?? Object data) {
????if (mCallbacks != null) {
????String lastBecause = null;
????if (mHost != null) {
????lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
????mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
????}
????try {
????if (DEBUG) Log.v(TAG?? " onLoadFinished in " + loader + ": "
????+ loader.dataToString(data));
????//?????????????????callback????????????onLoadFinished????????????????д?????
????mCallbacks.onLoadFinished(loader?? data);
????} finally {
????if (mHost != null) {
????mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
????}
????}
????mDeliveredData = true;
????}
????}
????????????? ?????Loader????е? ??????? ??????????????????????????????? ????????????????ι????ɡ?
????????????????activity???
????//??activity??onStart????
????protected void onStart() {
????if (DEBUG_LIFECYCLE) Slog.v(TAG?? "onStart " + this);
????mCalled = true;
????//??????12?? ??????mFragements ??????activity?????????????????? ???????????? ????????????? ?????????????й??activity??fragment??ν??????
????mFragments.doLoaderStart();
????getApplication().dispatchActivityStarted(this);
????}
????//??????????????? ??????manager??dostart????
????void doLoaderStart() {
????if (mLoadersStarted) {
????return;
????}
????mLoadersStarted = true;
????if (mLoaderManager != null) {
????//?????30??
????mLoaderManager.doStart();
????} else if (!mCheckedForLoaderManager) {
????mLoaderManager = getLoaderManager("(root)"?? mLoadersStarted?? false);
????}
????mCheckedForLoaderManager = true;
????}
????//------------------?????????????activity????????? ????LoaderManger??????
????void doStart() {
????if (DEBUG) Log.v(TAG?? "Starting in " + this);
????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--) {
????//?????50??
????mLoaders.valueAt(i).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) {
????//???onCreateLoader?????????? ???????????? ????ù??????????????????в???????????ε??????
????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;
????}
????//???????????startLoading???? ?????????????mLoader?? ?????88??
????mLoader.startLoading();
????}
????}
????//88- 98????loader????????
????public final void startLoading() {
????mStarted = true;
????mReset = false;
????mAbandoned = false;
????onStartLoading();
????}
????//?????????????????????????????? ????????????????????????cursorloader????????????????ɡ?
????protected void onStartLoading() {
????}
????//99- 112?? ??cursorLoader?????????
????//???????? ????????forceload???? ???????????????????? ???????????asynctask ????background????
????//????????? ????????????????????????????? ??????????????????б????μ?????????????????????? ??????????
????//??????????????????activity??onStart????????? ????????Loader???????onStartLoading????????????????????
????//Loader???????????? ?????б仯?????????? ???????????????????????
????protected void onStartLoading() {
????if (mCursor != null) {
????deliverResult(mCursor);
????}
????if (takeContentChanged() || mCursor == null) {
????forceLoad();
????}
????}
????//114-139?? ? http://developer.android.com/intl/zh-cn/reference/android/content/AsyncTaskLoader.html ??????? AppListLoader ????????
????//??138?? ??????????forceLoad ???????????applist??б仯????? ??????????????б?
????/**
????* Handles a request to start the Loader.
????*/
????@Override protected void onStartLoading() {
????if (mApps != null) {
????// If we currently have a result available?? deliver it
????// immediately.
????deliverResult(mApps);
????}
????// Start watching for changes in the app data.
????if (mPackageObserver == null) {
????mPackageObserver = new PackageIntentReceiver(this);
????}
????// Has something interesting in the configuration changed since we
????// last built the app list?
????boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());
????if (takeContentChanged() || mApps == null || configChange) {
????// If the data has changed since the last time it was loaded
????// or is not currently available?? start a load.
????forceLoad();
????}
????}
????start???? ???????????? ???????????stop????? ??????? ???????????? ???????????????????????????????????????????
????//??????????fragment??onDestroy???? ????????
????public void onDestroy() {
????mCalled = true;
????//Log.v("foo"?? "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager
????// + " mLoaderManager=" + mLoaderManager);
????if (!mCheckedForLoaderManager) {
????mCheckedForLoaderManager = true;
????mLoaderManager = mHost.getLoaderManager(mWho?? mLoadersStarted?? false);
????}
????if (mLoaderManager != null) {
????//?????16??
????mLoaderManager.doDestroy();
????}
????}
????//???????? ????fragment?? ??????????loadermanger??
????void doDestroy() {
????if (!mRetaining) {
????if (DEBUG) Log.v(TAG?? "Destroying Active in " + this);
????for (int i = mLoaders.size()-1; i >= 0; i--) {
????mLoaders.valueAt(i).destroy();
????}
????mLoaders.clear();
????}
????if (DEBUG) Log.v(TAG?? "Destroying Inactive in " + this);
????for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
????mInactiveLoaders.valueAt(i).destroy();
????}
????mInactiveLoaders.clear();
????}
????//???????destroy???? ?????????????????? ????clear???л????
????void destroy() {
????if (DEBUG) Log.v(TAG?? " Destroying: " + this);
????mDestroyed = true;
????boolean needReset = mDeliveredData;
????mDeliveredData = false;
????if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
????if (DEBUG) Log.v(TAG?? " Reseting: " + this);
????String lastBecause = null;
????if (mHost != null) {
????lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
????mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
????}
????try {
????mCallbacks.onLoaderReset(mLoader);
????} finally {
????if (mHost != null) {
????mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
????}
????}
????}
????mCallbacks = null;
????mData = null;
????mHaveData = false;
????if (mLoader != null) {
????if (mListenerRegistered) {
????mListenerRegistered = false;
????mLoader.unregisterListener(this);
????mLoader.unregisterOnLoadCanceledListener(this);
????}
????//?????????rest
????mLoader.reset();
????}
????if (mPendingLoader != null) {
????mPendingLoader.destroy();
????}
????}
????//????????????loader?????? ???????? ??fragement destroy??????????????????????onReset????
????public void reset() {
????onReset();
????mReset = true;
????mStarted = false;
????mAbandoned = false;
????mContentChanged = false;
????mProcessingChange = false;
????}
????/**
????* Subclasses must implement this to take care of resetting their loader??
????* as per {@link #reset()}. This is not called by clients directly??
????* but as a result of a call to {@link #reset()}.
????* This will always be called from the process's main thread.
????*/
????protected void onReset() {
????}
????//??????cURSORLOADER??????? ??????????cursor
????@Override
????protected void onReset() {
????super.onReset();
????// Ensure the loader is stopped
????onStopLoading();
????if (mCursor != null && !mCursor.isClosed()) {
????mCursor.close();
????}
????mCursor = null;
????}
????//????? ??????????applistloader??????? ????????????????????????????
????//??????????? ??????? loader?????????????????????Щ??????????????????
????//??????д????????????????? loader???????????? ???????????????????????????????????? ???????
????@Override protected void onReset() {
????super.onReset();
????// Ensure the loader is stopped
????onStopLoading();
????// At this point we can release the resources associated with 'apps'
????// if needed.
????if (mApps != null) {
????onReleaseResources(mApps);
????mApps = null;
????}
????// Stop monitoring for changes.
????if (mPackageObserver != null) {
????getContext().unregisterReceiver(mPackageObserver);
????mPackageObserver = null;
????}
????}
???????????????????????漰???????????????????SPASVOС??(021-61079698-8054)?????????????????????????
??????
Android???????????????Щ???????????Android????????????????????????Щ??Android ??????????????????????????APP?????android???????????????Android App ?????????Android Unit Test ?????Android?????????Robolectric3.0????(?)Android??????????????Android Studio???????????Android????MySQL????????????????Android MVP???????Android ?????????ActiveAndroid??дAndroid??????????????????????Android????????Java??????????Android????????Java8Java / Android ????????????????Щ??
???·???
??????????????????
2023/3/23 14:23:39???д?ò??????????
2023/3/22 16:17:39????????????????????Щ??
2022/6/14 16:14:27??????????????????????????
2021/10/18 15:37:44???????????????
2021/9/17 15:19:29???·???????·
2021/9/14 15:42:25?????????????
2021/5/28 17:25:47??????APP??????????
2021/5/8 17:01:11????????
?????????App Bug???????????????????????Jmeter?????????QC??????APP????????????????app?????е????????jenkins+testng+ant+webdriver??????????????JMeter????HTTP???????Selenium 2.0 WebDriver ??????