???????????? ?????????????????????????????app list??仯??????????????????e?????????????????????????????app list??仯 ?????????棬??????? ????app list???????????????????? ?????????? ??????demo?? ????????????????????loader???????????????????????
????/**
????* Helper class to look for interesting changes to the installed apps
????* so that the loader can be updated.
????*/
????public static class PackageIntentReceiver extends BroadcastReceiver {
????final AppListLoader mLoader;
????//????????????????? ??????? ????????loader
????public PackageIntentReceiver(AppListLoader loader) {
????mLoader = loader;
????IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
????filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
????filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
????filter.addDataScheme("package");
????mLoader.getContext().registerReceiver(this?? filter);
????// Register for events related to sdcard installation.
????IntentFilter sdFilter = new IntentFilter();
????sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
????sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
????//???????? ?????loader????????????????
????mLoader.getContext().registerReceiver(this?? sdFilter);
????}
????//?????????? ?????鶼????????????????loader??onContentChanged????
????@Override public void onReceive(Context context?? Intent intent) {
????// Tell the loader about the change.
????mLoader.onContentChanged();
????}
????}
???????????25-26?? ?????? loader??onContentChanged?????????????????loader
????/**
????* A custom Loader that loads all of the installed applications.
????*/
????public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {
????final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
????final PackageManager mPm;
????List<AppEntry> mApps;
????PackageIntentReceiver mPackageObserver;
????public AppListLoader(Context context) {
????super(context);
????// Retrieve the package manager for later use; note we don't
????// use 'context' directly but instead the save global application
????// context returned by getContext().
????mPm = getContext().getPackageManager();
????}
????//????????????????????????????????????????????? ??applist ???????????
????//onLoadFinished ?????????????棡
????@Override public List<AppEntry> loadInBackground() {
????// Retrieve all known applications.
????List<ApplicationInfo> apps = mPm.getInstalledApplications(
????PackageManager.GET_UNINSTALLED_PACKAGES |
????PackageManager.GET_DISABLED_COMPONENTS);
????if (apps == null) {
????apps = new ArrayList<ApplicationInfo>();
????}
????final Context context = getContext();
????// Create corresponding array of entries and load their labels.
????List<AppEntry> entries = new ArrayList<AppEntry>(apps.size());
????for (int i=0; i<apps.size(); i++) {
????AppEntry entry = new AppEntry(this?? apps.get(i));
????entry.loadLabel(context);
????entries.add(entry);
????}
????// Sort the list.
????Collections.sort(entries?? ALPHA_COMPARATOR);
????// Done!
????return entries;
????}
????/**
????* Called when there is new data to deliver to the client.  The
????* super class will take care of delivering it; the implementation
????* here just adds a little more logic.
????*/
????@Override public void deliverResult(List<AppEntry> apps) {
????if (isReset()) {
????// An async query came in while the loader is stopped.  We
????// don't need the result.
????if (apps != null) {
????onReleaseResources(apps);
????}
????}
????List<AppEntry> oldApps = mApps;
????mApps = apps;
????if (isStarted()) {
????// If the Loader is currently started?? we can immediately
????// deliver its results.
????super.deliverResult(apps);
????}
????// At this point we can release the resources associated with
????// 'oldApps' if needed; now that the new result is delivered we
????// know that it is no longer in use.
????if (oldApps != null) {
????onReleaseResources(oldApps);
????}
????}
????/**
????* 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();
????}
????}
????/**
????* Handles a request to stop the Loader.
????*/
????@Override protected void onStopLoading() {
????// Attempt to cancel the current load task if possible.
????cancelLoad();
????}
????/**
????* Handles a request to cancel a load.
????*/
????@Override public void onCanceled(List<AppEntry> apps) {
????super.onCanceled(apps);
????// At this point we can release the resources associated with 'apps'
????// if needed.
????onReleaseResources(apps);
????}
????/**
????* Handles a request to completely reset the 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;
????}
????}
????/**
????* Helper function to take care of releasing resources associated
????* with an actively loaded data set.
????*/
????protected void onReleaseResources(List<AppEntry> apps) {
????// For a simple List<> there is nothing to do.  For something
????// like a Cursor?? we would close it here.
????}
????}
???????????????????????????loader?? ?????????????????????? ???????? ????loader??onContentChanged?????????????????? AppListLoader???loadInBackGround??????????loadInBackGround????????? ??????????onLoadFinished??????? ???????????? ??????????????loader????????????????????????????????loader?????????????????????????????????????? ??????????????????????????????????????? ?????????????????????????????????????Ρ?
???????? ????????????????????????
????public class CursorLoader extends AsyncTaskLoader<Cursor> {
????public abstract class AsyncTaskLoader<D> extends Loader<D> {
????public class Loader<D> {
??????????????????????????????????????????Loader ????????????????????????????????????????AsyncTaskLoader ???????????????
??????????????????????CursorLoader????????????????? ???????????????Cursor???????????Loader??????????????? ??????????????????
??????????demo?? ?????????List??
????????? ??????????????????μ????????????????????
??????????3??demo???????????????fragment??activity?? ????loader??????? ????????? ????????????????????????fragment??
????fragment?? ????????????????
????//??????????????????loader
????getLoaderManager().initLoader(0?? null?? this);
???????get?????manager ???init????????????fragment?????
????//?????????????fragment????????loadermanager???
????public LoaderManager getLoaderManager() {
????if (mLoaderManager != null) {
????return mLoaderManager;
????}
????//mHost?????? ??fragment????????????fragment ???????activity??
????if (mHost == null) {
????throw new IllegalStateException("Fragment " + this + " not attached to Activity");
????}
????mCheckedForLoaderManager = true;
????mLoaderManager = mHost.getLoaderManager(mWho?? mLoadersStarted?? true);
????return mLoaderManager;
????}
??????? ??????? fragment??getLoaderManager??????activity??getLoader??????????????activity???????? ??
????//??activty??????????????????? ?????????
????LoaderManagerImpl getLoaderManagerImpl() {
????if (mLoaderManager != null) {
????return mLoaderManager;
????}
????mCheckedForLoaderManager = true;
????mLoaderManager = getLoaderManager("(root)"?? mLoadersStarted?? true /*create*/);
????return mLoaderManager;
????}
????//??????????? ????????????? who??????????? ?????activity??????????????????who?????root
????//???????actvity ????????loadermanger ????????????????fragment?? ???????????????????
????// Internal unique name for this fragment;
????//String mWho;
????//????????fragment??mWho?????????????activty?У???????????map?????key ??????loadermanager
????//key??fragment?????????????????activity?????activity??????????root)??
????LoaderManagerImpl getLoaderManager(String who?? boolean started?? boolean create) {
????if (mAllLoaderManagers == null) {
????mAllLoaderManagers = new ArrayMap<String?? LoaderManager>();
????}
????LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
????if (lm == null) {
????if (create) {
????lm = new LoaderManagerImpl(who?? this?? started);
????mAllLoaderManagers.put(who?? lm);
????}
????} else {
????lm.updateHostController(this);
????}
????return lm;
????}
?????? ???????? ???????????????????????????loadermanager????洢??activity?е??????fragment??loadermanager??????????map????? get????????manager??????????????????????????????
????public abstract class LoaderManager {
????/**
????* Callback interface for a client to interact with the manager.
????*/
????public interface LoaderCallbacks<D> {
????/**
????* Instantiate and return a new Loader for the given ID.
????*
????* @param id The ID whose loader is to be created.
????* @param args Any arguments supplied by the caller.
????* @return Return a new Loader instance that is ready to start loading.
????*/
????public Loader<D> onCreateLoader(int id?? Bundle args);
????/**
????* Called when a previously created loader has finished its load.  Note
????* that normally an application is <em>not</em> allowed to commit fragment
????* transactions while in this call?? since it can happen after an
????* activity's state is saved.  See {@link FragmentManager#beginTransaction()
????* FragmentManager.openTransaction()} for further discussion on this.
????*
????* <p>This function is guaranteed to be called prior to the release of
????* the last data that was supplied for this Loader.  At this point
????* you should remove all use of the old data (since it will be released
????* soon)?? but should not do your own release of the data since its Loader
????* owns it and will take care of that.  The Loader will take care of
????* management of its data so you don't have to.  In particular:
????*
????* <ul>
????* <li> <p>The Loader will monitor for changes to the data?? and report
????* them to you through new calls here.  You should not monitor the
????* data yourself.  For example?? if the data is a {@link android.database.Cursor}
????* and you place it in a {@link android.widget.CursorAdapter}?? use
????* the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context??
????* android.database.Cursor?? int)} constructor <em>without</em> passing
????* in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY}
????* or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER}
????* (that is?? use 0 for the flags argument).  This prevents the CursorAdapter
????* from doing its own observing of the Cursor?? which is not needed since
????* when a change happens you will get a new Cursor throw another call
????* here.
????* <li> The Loader will release the data once it knows the application
????* is no longer using it.  For example?? if the data is
????* a {@link android.database.Cursor} from a {@link android.content.CursorLoader}??
????* you should not call close() on it yourself.  If the Cursor is being placed in a
????* {@link android.widget.CursorAdapter}?? you should use the
????* {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)}
????* method so that the old Cursor is not closed.
????* </ul>
????*
????* @param loader The Loader that has finished.
????* @param data The data generated by the Loader.
????*/
????public void onLoadFinished(Loader<D> loader?? D data);
????/**
????* Called when a previously created loader is being reset?? and thus
????* making its data unavailable.  The application should at this point
????* remove any references it has to the Loader's data.
????*
????* @param loader The Loader that is being reset.
????*/
????public void onLoaderReset(Loader<D> loader);
????}
?????????? loadermanger ??????????????????????Щ ?????????????????Щ?????????????÷? ????3??demo?? ???????????????????
?????????????????????????????????????????????get?????maganger??? ???????????????init???? ?????????????????????????
????public <D> Loader<D> initLoader(int id?? Bundle args?? LoaderManager.LoaderCallbacks<D> callback) {
????if (mCreatingLoader) {
????throw new IllegalStateException("Called while creating a loader");
????}
????//??????????????л???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;
????}
????//????????????loader
????final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(0);
????//???????????н?????loader
????final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(0);
????//??????????loader????????????????????????????????callback ???????
????//?????????????3??demo?????????????fragemet??activity??????callback
????//????????????this?????? ???????????????? ???????loader ???????????
????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;
????}
????}
?????? ?????????????????? callback???????loadermageer?????????????? ???????????????????????????????????????仯????? ?????????????????????loader????????
???????????Loader?????????????????
????//????????????? ???????仯????? ????????onContentChanged????
????public final class ForceLoadContentObserver extends ContentObserver {
????public ForceLoadContentObserver() {
????super(new Handler());
????}
????@Override
????public boolean deliverSelfNotifications() {
????return true;
????}
????@Override
????public void onChange(boolean selfChange) {
????onContentChanged();
????}
????}
????//??????2????????????? ?????????????仯????? ??????????????????????????????
????//onForceLoad??????? ??onForceLoad?????????????? ???AsyncTaskLoader??onForceLoad??????