返回博主主页

android Loader

安卓学习之路之Loader的简单用法

一、看看loader包目录结构:

 

 

1、LoaderManager

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.loader.app;

import android.os.Bundle;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.loader.content.Loader;

import java.io.FileDescriptor;
import java.io.PrintWriter;

/**
 * Static library support version of the framework's {@link android.app.LoaderManager}.
 * Used to write apps that run on platforms prior to Android 3.0.  When running
 * on Android 3.0 or above, this implementation is still used; it does not try
 * to switch to the framework's implementation.  See the framework SDK
 * documentation for a class overview.
 *
 * <p>Your activity must derive from {@link androidx.fragment.app.FragmentActivity} to use this.
 */
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.
         *
         * <p>This will always be called from the process's main thread.
         *
         * @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.
         */
        @MainThread
        @NonNull
        Loader<D> onCreateLoader(int id, @Nullable 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 androidx.fragment.app.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>
         *
         * <p>This will always be called from the process's main thread.
         *
         * @param loader The Loader that has finished.
         * @param data The data generated by the Loader.
         */
        @MainThread
        void onLoadFinished(@NonNull 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.
         *
         * <p>This will always be called from the process's main thread.
         *
         * @param loader The Loader that is being reset.
         */
        @MainThread
        void onLoaderReset(@NonNull Loader<D> loader);
    }

    /**
     * Gets a LoaderManager associated with the given owner, such as a {@link androidx.fragment.app.FragmentActivity} or
     * {@link androidx.fragment.app.Fragment}.
     *
     * @param owner The owner that should be used to create the returned LoaderManager
     * @param <T> A class that maintains its own {@link android.arch.lifecycle.Lifecycle} and
     *           {@link android.arch.lifecycle.ViewModelStore}. For instance,
     *           {@link androidx.fragment.app.FragmentActivity} or {@link androidx.fragment.app.Fragment}.
     * @return A valid LoaderManager
     */
    @NonNull
    public static <T extends LifecycleOwner & ViewModelStoreOwner> LoaderManager getInstance(
            @NonNull T owner) {
        return new LoaderManagerImpl(owner, owner.getViewModelStore());
    }

    /**
     * Ensures a loader is initialized and active.  If the loader doesn't
     * already exist, one is created and (if the activity/fragment is currently
     * started) starts the loader.  Otherwise the last created
     * loader is re-used.
     *
     * <p>In either case, the given callback is associated with the loader, and
     * will be called as the loader state changes.  If at the point of call
     * the caller is in its started state, and the requested loader
     * already exists and has generated its data, then
     * callback {@link LoaderCallbacks#onLoadFinished} will
     * be called immediately (inside of this function), so you must be prepared
     * for this to happen.
     *
     * <p>Must be called from the process's main thread.
     *
     * @param id A unique identifier for this loader.  Can be whatever you want.
     * Identifiers are scoped to a particular LoaderManager instance.
     * @param args Optional arguments to supply to the loader at construction.
     * If a loader already exists (a new one does not need to be created), this
     * parameter will be ignored and the last arguments continue to be used.
     * @param callback Interface the LoaderManager will call to report about
     * changes in the state of the loader.  Required.
     */
    @MainThread
    @NonNull
    public abstract <D> Loader<D> initLoader(int id, @Nullable Bundle args,
            @NonNull LoaderManager.LoaderCallbacks<D> callback);

    /**
     * Starts a new or restarts an existing {@link android.content.Loader} in
     * this manager, registers the callbacks to it,
     * and (if the activity/fragment is currently started) starts loading it.
     * If a loader with the same id has previously been
     * started it will automatically be destroyed when the new loader completes
     * its work. The callback will be delivered before the old loader
     * is destroyed.
     *
     * <p>Must be called from the process's main thread.
     *
     * @param id A unique identifier for this loader.  Can be whatever you want.
     * Identifiers are scoped to a particular LoaderManager instance.
     * @param args Optional arguments to supply to the loader at construction.
     * @param callback Interface the LoaderManager will call to report about
     * changes in the state of the loader.  Required.
     */
    @MainThread
    @NonNull
    public abstract <D> Loader<D> restartLoader(int id, @Nullable Bundle args,
            @NonNull LoaderManager.LoaderCallbacks<D> callback);

    /**
     * Stops and removes the loader with the given ID.  If this loader
     * had previously reported data to the client through
     * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call
     * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}.
     *
     * <p>Must be called from the process's main thread.
     */
    @MainThread
    public abstract void destroyLoader(int id);

    /**
     * Return the Loader with the given id or null if no matching Loader
     * is found.
     */
    @Nullable
    public abstract <D> Loader<D> getLoader(int id);

    /**
     * Mark all Loaders associated with this LoaderManager for redelivery of their current
     * data (if any), waiting for the next time the Loader is started if it is currently stopped.
     * In cases where no data has yet been delivered, this is effectively a no-op. In cases where
     * data has already been delivered via {@link LoaderCallbacks#onLoadFinished(Loader, Object)},
     * this will ensure that {@link LoaderCallbacks#onLoadFinished(Loader, Object)} is called again
     * with the same data.
     * <p>
     * Call this only if you are implementing a {@link LifecycleOwner} where the views/elements that
     * developers are likely to use in {@link LoaderCallbacks#onLoadFinished(Loader, Object)} can be
     * created and destroyed multiple times without the {@link LifecycleOwner} itself being
     * destroyed. Call this when the views/elements are being destroyed to ensure that the data
     * is redelivered upon recreation.
     */
    public abstract void markForRedelivery();

    /**
     * Print the LoaderManager's state into the given stream.
     *
     * @param prefix Text to print at the front of each line.
     * @param fd The raw file descriptor that the dump is being sent to.
     * @param writer A PrintWriter to which the dump is to be set.
     * @param args Additional arguments to the dump request.
     * @deprecated Use {@link #enableDebugLogging(boolean)} to understand the series of operations
     * performed by LoaderManager.
     */
    @Deprecated
    public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);

    /**
     * Control whether the framework's internal loader manager debugging
     * logs are turned on.  If enabled, you will see output in logcat as
     * the framework performs loader operations.
     */
    public static void enableDebugLogging(boolean enabled) {
        LoaderManagerImpl.DEBUG = enabled;
    }

    /**
     * Returns true if any loaders managed are currently running and have not
     * returned data to the application yet.
     */
    public boolean hasRunningLoaders() { return false; }
}
View Code

 

LoadManager.LoaderCallbacks

LoadManager.LoaderCallbacks::onCreateLoader

 

LoadManager.LoaderCallbacks::onLoadFinished

 

 

LoadManager.LoaderCallbacks::onLoaderReset

 

 

LoaderManager::getInstance

 

LoaderManager::initLoader

 

 

LoaderManager::restartLoader

 

 

 

 

LoaderManager::destroytLoader

 

 

 

LoaderManager::markForRedelivery

 

 

 

2、LoaderManagerImpl

  1 /*
  2  * Copyright 2018 The Android Open Source Project
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 package androidx.loader.app;
 18 
 19 import android.os.Bundle;
 20 import android.os.Looper;
 21 import android.util.Log;
 22 
 23 import androidx.annotation.MainThread;
 24 import androidx.annotation.NonNull;
 25 import androidx.annotation.Nullable;
 26 import androidx.collection.SparseArrayCompat;
 27 import androidx.core.util.DebugUtils;
 28 import androidx.lifecycle.LifecycleOwner;
 29 import androidx.lifecycle.MutableLiveData;
 30 import androidx.lifecycle.Observer;
 31 import androidx.lifecycle.ViewModel;
 32 import androidx.lifecycle.ViewModelProvider;
 33 import androidx.lifecycle.ViewModelStore;
 34 import androidx.loader.content.Loader;
 35 
 36 import java.io.FileDescriptor;
 37 import java.io.PrintWriter;
 38 import java.lang.reflect.Modifier;
 39 
 40 class LoaderManagerImpl extends LoaderManager {
 41     static final String TAG = "LoaderManager";
 42     static boolean DEBUG = false;
 43 
 44     /**
 45      * Class which manages the state of a {@link Loader} and its associated
 46      * {@link LoaderCallbacks}
 47      *
 48      * @param <D> Type of data the Loader handles
 49      */
 50     public static class LoaderInfo<D> extends MutableLiveData<D>
 51             implements Loader.OnLoadCompleteListener<D> {
 52 
 53         private final int mId;
 54         private final @Nullable Bundle mArgs;
 55         private final @NonNull Loader<D> mLoader;
 56         private LifecycleOwner mLifecycleOwner;
 57         private LoaderObserver<D> mObserver;
 58         private Loader<D> mPriorLoader;
 59 
 60         LoaderInfo(int id, @Nullable Bundle args, @NonNull Loader<D> loader,
 61                 @Nullable Loader<D> priorLoader) {
 62             mId = id;
 63             mArgs = args;
 64             mLoader = loader;
 65             mPriorLoader = priorLoader;
 66             mLoader.registerListener(id, this);
 67         }
 68 
 69         @NonNull
 70         Loader<D> getLoader() {
 71             return mLoader;
 72         }
 73 
 74         @Override
 75         protected void onActive() {
 76             if (DEBUG) Log.v(TAG, "  Starting: " + LoaderInfo.this);
 77             mLoader.startLoading();
 78         }
 79 
 80         @Override
 81         protected void onInactive() {
 82             if (DEBUG) Log.v(TAG, "  Stopping: " + LoaderInfo.this);
 83             mLoader.stopLoading();
 84         }
 85 
 86         /**
 87          * Set the {@link LoaderCallbacks} to associate with this {@link Loader}. This
 88          * removes any existing {@link LoaderCallbacks}.
 89          *
 90          * @param owner The lifecycle that should be used to start and stop the {@link Loader}
 91          * @param callback The new {@link LoaderCallbacks} to use
 92          * @return The {@link Loader} associated with this LoaderInfo
 93          */
 94         @MainThread
 95         @NonNull
 96         Loader<D> setCallback(@NonNull LifecycleOwner owner,
 97                 @NonNull LoaderCallbacks<D> callback) {
 98             LoaderObserver<D> observer = new LoaderObserver<>(mLoader, callback);
 99             // Add the new observer
100             observe(owner, observer);
101             // Loaders only support one observer at a time, so remove the current observer, if any
102             if (mObserver != null) {
103                 removeObserver(mObserver);
104             }
105             mLifecycleOwner = owner;
106             mObserver = observer;
107             return mLoader;
108         }
109 
110         void markForRedelivery() {
111             LifecycleOwner lifecycleOwner = mLifecycleOwner;
112             LoaderObserver<D> observer = mObserver;
113             if (lifecycleOwner != null && observer != null) {
114                 // Removing and re-adding the observer ensures that the
115                 // observer is called again, even if they had already
116                 // received the current data
117                 // Use super.removeObserver to avoid nulling out mLifecycleOwner & mObserver
118                 super.removeObserver(observer);
119                 observe(lifecycleOwner, observer);
120             }
121         }
122 
123         boolean isCallbackWaitingForData() {
124             //noinspection SimplifiableIfStatement
125             if (!hasActiveObservers()) {
126                 // No active observers means no one is waiting for data
127                 return false;
128             }
129             return mObserver != null && !mObserver.hasDeliveredData();
130         }
131 
132         @Override
133         public void removeObserver(@NonNull Observer<? super D> observer) {
134             super.removeObserver(observer);
135             // Clear out our references when the observer is removed to avoid leaking
136             mLifecycleOwner = null;
137             mObserver = null;
138         }
139 
140         /**
141          * Destroys this LoaderInfo, its underlying {@link #getLoader() Loader}, and removes any
142          * existing {@link androidx.loader.app.LoaderManager.LoaderCallbacks}.
143          *
144          * @param reset Whether the LoaderCallbacks and Loader should be reset.
145          * @return When reset is false, returns any Loader that still needs to be reset
146          */
147         @MainThread
148         Loader<D> destroy(boolean reset) {
149             if (DEBUG) Log.v(TAG, "  Destroying: " + this);
150             // First tell the Loader that we don't need it anymore
151             mLoader.cancelLoad();
152             mLoader.abandon();
153             // Then clean up the LoaderObserver
154             LoaderObserver<D> observer = mObserver;
155             if (observer != null) {
156                 removeObserver(observer);
157                 if (reset) {
158                     observer.reset();
159                 }
160             }
161             // Finally, clean up the Loader
162             mLoader.unregisterListener(this);
163             if ((observer != null && !observer.hasDeliveredData()) || reset) {
164                 mLoader.reset();
165                 return mPriorLoader;
166             }
167             return mLoader;
168         }
169 
170         @Override
171         public void onLoadComplete(@NonNull Loader<D> loader, @Nullable D data) {
172             if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);
173             if (Looper.myLooper() == Looper.getMainLooper()) {
174                 setValue(data);
175             } else {
176                 // The Loader#deliverResult method that calls this should
177                 // only be called on the main thread, so this should never
178                 // happen, but we don't want to lose the data
179                 if (DEBUG) {
180                     Log.w(TAG, "onLoadComplete was incorrectly called on a "
181                             + "background thread");
182                 }
183                 postValue(data);
184             }
185         }
186 
187         @Override
188         public void setValue(D value) {
189             super.setValue(value);
190             // Now that the new data has arrived, we can reset any prior Loader
191             if (mPriorLoader != null) {
192                 mPriorLoader.reset();
193                 mPriorLoader = null;
194             }
195         }
196 
197         @Override
198         public String toString() {
199             StringBuilder sb = new StringBuilder(64);
200             sb.append("LoaderInfo{");
201             sb.append(Integer.toHexString(System.identityHashCode(this)));
202             sb.append(" #");
203             sb.append(mId);
204             sb.append(" : ");
205             DebugUtils.buildShortClassTag(mLoader, sb);
206             sb.append("}}");
207             return sb.toString();
208         }
209 
210         @SuppressWarnings("deprecation")
211         public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
212             writer.print(prefix); writer.print("mId="); writer.print(mId);
213             writer.print(" mArgs="); writer.println(mArgs);
214             writer.print(prefix); writer.print("mLoader="); writer.println(mLoader);
215             mLoader.dump(prefix + "  ", fd, writer, args);
216             if (mObserver != null) {
217                 writer.print(prefix); writer.print("mCallbacks="); writer.println(mObserver);
218                 mObserver.dump(prefix + "  ", writer);
219             }
220             writer.print(prefix); writer.print("mData="); writer.println(
221                     getLoader().dataToString(getValue()));
222             writer.print(prefix); writer.print("mStarted="); writer.println(
223                     hasActiveObservers());
224         }
225     }
226 
227     /**
228      * Encapsulates the {@link LoaderCallbacks} as a {@link Observer}.
229      *
230      * @param <D> Type of data the LoaderCallbacks handles
231      */
232     static class LoaderObserver<D> implements Observer<D> {
233 
234         private final @NonNull Loader<D> mLoader;
235         private final @NonNull LoaderCallbacks<D> mCallback;
236 
237         private boolean mDeliveredData = false;
238 
239         LoaderObserver(@NonNull Loader<D> loader, @NonNull LoaderCallbacks<D> callback) {
240             mLoader = loader;
241             mCallback = callback;
242         }
243 
244         @Override
245         public void onChanged(@Nullable D data) {
246             if (DEBUG) {
247                 Log.v(TAG, "  onLoadFinished in " + mLoader + ": "
248                         + mLoader.dataToString(data));
249             }
250             mCallback.onLoadFinished(mLoader, data);
251             mDeliveredData = true;
252         }
253 
254         boolean hasDeliveredData() {
255             return mDeliveredData;
256         }
257 
258         @MainThread
259         void reset() {
260             if (mDeliveredData) {
261                 if (DEBUG) Log.v(TAG, "  Resetting: " + mLoader);
262                 mCallback.onLoaderReset(mLoader);
263             }
264         }
265 
266         @Override
267         public String toString() {
268             return mCallback.toString();
269         }
270 
271         public void dump(String prefix, PrintWriter writer) {
272             writer.print(prefix); writer.print("mDeliveredData="); writer.println(
273                     mDeliveredData);
274         }
275     }
276 
277     /**
278      * ViewModel responsible for retaining {@link LoaderInfo} instances across configuration changes
279      */
280     static class LoaderViewModel extends ViewModel {
281         private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() {
282             @NonNull
283             @Override
284             @SuppressWarnings("unchecked")
285             public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
286                 return (T) new LoaderViewModel();
287             }
288         };
289 
290         @NonNull
291         static LoaderViewModel getInstance(ViewModelStore viewModelStore) {
292             return new ViewModelProvider(viewModelStore, FACTORY).get(LoaderViewModel.class);
293         }
294 
295         private SparseArrayCompat<LoaderInfo> mLoaders = new SparseArrayCompat<>();
296         private boolean mCreatingLoader = false;
297 
298         void startCreatingLoader() {
299             mCreatingLoader = true;
300         }
301 
302         boolean isCreatingLoader() {
303             return mCreatingLoader;
304         }
305 
306         void finishCreatingLoader() {
307             mCreatingLoader = false;
308         }
309 
310         void putLoader(int id, @NonNull LoaderInfo info) {
311             mLoaders.put(id, info);
312         }
313 
314         @SuppressWarnings("unchecked")
315         <D> LoaderInfo<D> getLoader(int id) {
316             return mLoaders.get(id);
317         }
318 
319         void removeLoader(int id) {
320             mLoaders.remove(id);
321         }
322 
323         boolean hasRunningLoaders() {
324             int size = mLoaders.size();
325             for (int index = 0; index < size; index++) {
326                 LoaderInfo info = mLoaders.valueAt(index);
327                 if (info.isCallbackWaitingForData()) {
328                     return true;
329                 }
330             }
331             return false;
332         }
333 
334         void markForRedelivery() {
335             int size = mLoaders.size();
336             for (int index = 0; index < size; index++) {
337                 LoaderInfo info = mLoaders.valueAt(index);
338                 info.markForRedelivery();
339             }
340         }
341 
342         @Override
343         protected void onCleared() {
344             super.onCleared();
345             int size = mLoaders.size();
346             for (int index = 0; index < size; index++) {
347                 LoaderInfo info = mLoaders.valueAt(index);
348                 info.destroy(true);
349             }
350             mLoaders.clear();
351         }
352 
353         public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
354             if (mLoaders.size() > 0) {
355                 writer.print(prefix); writer.println("Loaders:");
356                 String innerPrefix = prefix + "    ";
357                 for (int i = 0; i < mLoaders.size(); i++) {
358                     LoaderInfo info = mLoaders.valueAt(i);
359                     writer.print(prefix); writer.print("  #"); writer.print(mLoaders.keyAt(i));
360                     writer.print(": "); writer.println(info.toString());
361                     info.dump(innerPrefix, fd, writer, args);
362                 }
363             }
364         }
365     }
366 
367     private final @NonNull LifecycleOwner mLifecycleOwner;
368     private final @NonNull LoaderViewModel mLoaderViewModel;
369 
370     LoaderManagerImpl(@NonNull LifecycleOwner lifecycleOwner,
371             @NonNull ViewModelStore viewModelStore) {
372         mLifecycleOwner = lifecycleOwner;
373         mLoaderViewModel = LoaderViewModel.getInstance(viewModelStore);
374     }
375 
376     @MainThread
377     @NonNull
378     private <D> Loader<D> createAndInstallLoader(int id, @Nullable Bundle args,
379             @NonNull LoaderCallbacks<D> callback, @Nullable Loader<D> priorLoader) {
380         LoaderInfo<D> info;
381         try {
382             mLoaderViewModel.startCreatingLoader();
383             Loader<D> loader = callback.onCreateLoader(id, args);
384             if (loader == null) {
385                 throw new IllegalArgumentException("Object returned from onCreateLoader "
386                         + "must not be null");
387             }
388             if (loader.getClass().isMemberClass()
389                     && !Modifier.isStatic(loader.getClass().getModifiers())) {
390                 throw new IllegalArgumentException("Object returned from onCreateLoader "
391                         + "must not be a non-static inner member class: "
392                         + loader);
393             }
394             info = new LoaderInfo<>(id, args, loader, priorLoader);
395             if (DEBUG) Log.v(TAG, "  Created new loader " + info);
396             mLoaderViewModel.putLoader(id, info);
397         } finally {
398             mLoaderViewModel.finishCreatingLoader();
399         }
400         return info.setCallback(mLifecycleOwner, callback);
401     }
402 
403     @MainThread
404     @NonNull
405     @Override
406     public <D> Loader<D> initLoader(int id, @Nullable Bundle args,
407             @NonNull LoaderCallbacks<D> callback) {
408         if (mLoaderViewModel.isCreatingLoader()) {
409             throw new IllegalStateException("Called while creating a loader");
410         }
411         if (Looper.getMainLooper() != Looper.myLooper()) {
412             throw new IllegalStateException("initLoader must be called on the main thread");
413         }
414 
415         LoaderInfo<D> info = mLoaderViewModel.getLoader(id);
416 
417         if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
418 
419         if (info == null) {
420             // Loader doesn't already exist; create.
421             return createAndInstallLoader(id, args, callback, null);
422         } else {
423             if (DEBUG) Log.v(TAG, "  Re-using existing loader " + info);
424             return info.setCallback(mLifecycleOwner, callback);
425         }
426     }
427 
428     @MainThread
429     @NonNull
430     @Override
431     public <D> Loader<D> restartLoader(int id, @Nullable Bundle args,
432             @NonNull LoaderCallbacks<D> callback) {
433         if (mLoaderViewModel.isCreatingLoader()) {
434             throw new IllegalStateException("Called while creating a loader");
435         }
436         if (Looper.getMainLooper() != Looper.myLooper()) {
437             throw new IllegalStateException("restartLoader must be called on the main thread");
438         }
439 
440         if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args);
441         LoaderInfo<D> info = mLoaderViewModel.getLoader(id);
442         Loader<D> priorLoader = null;
443         if (info != null) {
444             priorLoader = info.destroy(false);
445         }
446         // And create a new Loader
447         return createAndInstallLoader(id, args, callback, priorLoader);
448     }
449 
450     @MainThread
451     @Override
452     public void destroyLoader(int id) {
453         if (mLoaderViewModel.isCreatingLoader()) {
454             throw new IllegalStateException("Called while creating a loader");
455         }
456         if (Looper.getMainLooper() != Looper.myLooper()) {
457             throw new IllegalStateException("destroyLoader must be called on the main thread");
458         }
459 
460         if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id);
461         LoaderInfo info = mLoaderViewModel.getLoader(id);
462         if (info != null) {
463             info.destroy(true);
464             mLoaderViewModel.removeLoader(id);
465         }
466     }
467 
468     @Nullable
469     @Override
470     public <D> Loader<D> getLoader(int id) {
471         if (mLoaderViewModel.isCreatingLoader()) {
472             throw new IllegalStateException("Called while creating a loader");
473         }
474 
475         LoaderInfo<D> info = mLoaderViewModel.getLoader(id);
476         return info != null ? info.getLoader() : null;
477     }
478 
479     @Override
480     public void markForRedelivery() {
481         mLoaderViewModel.markForRedelivery();
482     }
483 
484     @Override
485     public String toString() {
486         StringBuilder sb = new StringBuilder(128);
487         sb.append("LoaderManager{");
488         sb.append(Integer.toHexString(System.identityHashCode(this)));
489         sb.append(" in ");
490         DebugUtils.buildShortClassTag(mLifecycleOwner, sb);
491         sb.append("}}");
492         return sb.toString();
493     }
494 
495     @Deprecated
496     @Override
497     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
498         mLoaderViewModel.dump(prefix, fd, writer, args);
499     }
500 
501     @Override
502     public boolean hasRunningLoaders() {
503         return mLoaderViewModel.hasRunningLoaders();
504     }
505 }
View Code

 LoadInfo就是LiveData
LoaderViewModel就是ViewModel

LoaderObserver就是Observer

posted @ 2022-03-13 23:27  懒惰的星期六  阅读(28)  评论(0编辑  收藏  举报

Welcome to here

主页