• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 import androidx.annotation.MainThread;
22 import androidx.annotation.NonNull;
23 import androidx.annotation.Nullable;
24 import androidx.lifecycle.LifecycleOwner;
25 import androidx.lifecycle.ViewModelStoreOwner;
26 import androidx.loader.content.Loader;
27 
28 import java.io.FileDescriptor;
29 import java.io.PrintWriter;
30 
31 /**
32  * Static library support version of the framework's {@link android.app.LoaderManager}.
33  * Used to write apps that run on platforms prior to Android 3.0.  When running
34  * on Android 3.0 or above, this implementation is still used; it does not try
35  * to switch to the framework's implementation.  See the framework SDK
36  * documentation for a class overview.
37  *
38  * <p>Your activity must derive from {@link androidx.fragment.app.FragmentActivity} to use this.
39  */
40 public abstract class LoaderManager {
41     /**
42      * Callback interface for a client to interact with the manager.
43      */
44     public interface LoaderCallbacks<D> {
45         /**
46          * Instantiate and return a new Loader for the given ID.
47          *
48          * <p>This will always be called from the process's main thread.
49          *
50          * @param id The ID whose loader is to be created.
51          * @param args Any arguments supplied by the caller.
52          * @return Return a new Loader instance that is ready to start loading.
53          */
54         @MainThread
55         @NonNull
onCreateLoader(int id, @Nullable Bundle args)56         Loader<D> onCreateLoader(int id, @Nullable Bundle args);
57 
58         /**
59          * Called when a previously created loader has finished its load.  Note
60          * that normally an application is <em>not</em> allowed to commit fragment
61          * transactions while in this call, since it can happen after an
62          * activity's state is saved.  See {@link androidx.fragment.app.FragmentManager#beginTransaction()
63          * FragmentManager.openTransaction()} for further discussion on this.
64          *
65          * <p>This function is guaranteed to be called prior to the release of
66          * the last data that was supplied for this Loader.  At this point
67          * you should remove all use of the old data (since it will be released
68          * soon), but should not do your own release of the data since its Loader
69          * owns it and will take care of that.  The Loader will take care of
70          * management of its data so you don't have to.  In particular:
71          *
72          * <ul>
73          * <li> <p>The Loader will monitor for changes to the data, and report
74          * them to you through new calls here.  You should not monitor the
75          * data yourself.  For example, if the data is a {@link android.database.Cursor}
76          * and you place it in a {@link android.widget.CursorAdapter}, use
77          * the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context,
78          * android.database.Cursor, int)} constructor <em>without</em> passing
79          * in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY}
80          * or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER}
81          * (that is, use 0 for the flags argument).  This prevents the CursorAdapter
82          * from doing its own observing of the Cursor, which is not needed since
83          * when a change happens you will get a new Cursor throw another call
84          * here.
85          * <li> The Loader will release the data once it knows the application
86          * is no longer using it.  For example, if the data is
87          * a {@link android.database.Cursor} from a {@link android.content.CursorLoader},
88          * you should not call close() on it yourself.  If the Cursor is being placed in a
89          * {@link android.widget.CursorAdapter}, you should use the
90          * {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)}
91          * method so that the old Cursor is not closed.
92          * </ul>
93          *
94          * <p>This will always be called from the process's main thread.
95          *
96          * @param loader The Loader that has finished.
97          * @param data The data generated by the Loader.
98          */
99         @MainThread
onLoadFinished(@onNull Loader<D> loader, D data)100         void onLoadFinished(@NonNull Loader<D> loader, D data);
101 
102         /**
103          * Called when a previously created loader is being reset, and thus
104          * making its data unavailable.  The application should at this point
105          * remove any references it has to the Loader's data.
106          *
107          * <p>This will always be called from the process's main thread.
108          *
109          * @param loader The Loader that is being reset.
110          */
111         @MainThread
onLoaderReset(@onNull Loader<D> loader)112         void onLoaderReset(@NonNull Loader<D> loader);
113     }
114 
115     /**
116      * Gets a LoaderManager associated with the given owner, such as a {@link androidx.fragment.app.FragmentActivity} or
117      * {@link androidx.fragment.app.Fragment}.
118      *
119      * @param owner The owner that should be used to create the returned LoaderManager
120      * @param <T> A class that maintains its own {@link android.arch.lifecycle.Lifecycle} and
121      *           {@link android.arch.lifecycle.ViewModelStore}. For instance,
122      *           {@link androidx.fragment.app.FragmentActivity} or {@link androidx.fragment.app.Fragment}.
123      * @return A valid LoaderManager
124      */
125     @NonNull
getInstance( @onNull T owner)126     public static <T extends LifecycleOwner & ViewModelStoreOwner> LoaderManager getInstance(
127             @NonNull T owner) {
128         return new LoaderManagerImpl(owner, owner.getViewModelStore());
129     }
130 
131     /**
132      * Ensures a loader is initialized and active.  If the loader doesn't
133      * already exist, one is created and (if the activity/fragment is currently
134      * started) starts the loader.  Otherwise the last created
135      * loader is re-used.
136      *
137      * <p>In either case, the given callback is associated with the loader, and
138      * will be called as the loader state changes.  If at the point of call
139      * the caller is in its started state, and the requested loader
140      * already exists and has generated its data, then
141      * callback {@link LoaderCallbacks#onLoadFinished} will
142      * be called immediately (inside of this function), so you must be prepared
143      * for this to happen.
144      *
145      * <p>Must be called from the process's main thread.
146      *
147      * @param id A unique identifier for this loader.  Can be whatever you want.
148      * Identifiers are scoped to a particular LoaderManager instance.
149      * @param args Optional arguments to supply to the loader at construction.
150      * If a loader already exists (a new one does not need to be created), this
151      * parameter will be ignored and the last arguments continue to be used.
152      * @param callback Interface the LoaderManager will call to report about
153      * changes in the state of the loader.  Required.
154      */
155     @MainThread
156     @NonNull
initLoader(int id, @Nullable Bundle args, @NonNull LoaderManager.LoaderCallbacks<D> callback)157     public abstract <D> Loader<D> initLoader(int id, @Nullable Bundle args,
158             @NonNull LoaderManager.LoaderCallbacks<D> callback);
159 
160     /**
161      * Starts a new or restarts an existing {@link android.content.Loader} in
162      * this manager, registers the callbacks to it,
163      * and (if the activity/fragment is currently started) starts loading it.
164      * If a loader with the same id has previously been
165      * started it will automatically be destroyed when the new loader completes
166      * its work. The callback will be delivered before the old loader
167      * is destroyed.
168      *
169      * <p>Must be called from the process's main thread.
170      *
171      * @param id A unique identifier for this loader.  Can be whatever you want.
172      * Identifiers are scoped to a particular LoaderManager instance.
173      * @param args Optional arguments to supply to the loader at construction.
174      * @param callback Interface the LoaderManager will call to report about
175      * changes in the state of the loader.  Required.
176      */
177     @MainThread
178     @NonNull
restartLoader(int id, @Nullable Bundle args, @NonNull LoaderManager.LoaderCallbacks<D> callback)179     public abstract <D> Loader<D> restartLoader(int id, @Nullable Bundle args,
180             @NonNull LoaderManager.LoaderCallbacks<D> callback);
181 
182     /**
183      * Stops and removes the loader with the given ID.  If this loader
184      * had previously reported data to the client through
185      * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call
186      * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}.
187      *
188      * <p>Must be called from the process's main thread.
189      */
190     @MainThread
destroyLoader(int id)191     public abstract void destroyLoader(int id);
192 
193     /**
194      * Return the Loader with the given id or null if no matching Loader
195      * is found.
196      */
197     @Nullable
getLoader(int id)198     public abstract <D> Loader<D> getLoader(int id);
199 
200     /**
201      * Mark all Loaders associated with this LoaderManager for redelivery of their current
202      * data (if any), waiting for the next time the Loader is started if it is currently stopped.
203      * In cases where no data has yet been delivered, this is effectively a no-op. In cases where
204      * data has already been delivered via {@link LoaderCallbacks#onLoadFinished(Loader, Object)},
205      * this will ensure that {@link LoaderCallbacks#onLoadFinished(Loader, Object)} is called again
206      * with the same data.
207      * <p>
208      * Call this only if you are implementing a {@link LifecycleOwner} where the views/elements that
209      * developers are likely to use in {@link LoaderCallbacks#onLoadFinished(Loader, Object)} can be
210      * created and destroyed multiple times without the {@link LifecycleOwner} itself being
211      * destroyed. Call this when the views/elements are being destroyed to ensure that the data
212      * is redelivered upon recreation.
213      */
markForRedelivery()214     public abstract void markForRedelivery();
215 
216     /**
217      * Print the LoaderManager's state into the given stream.
218      *
219      * @param prefix Text to print at the front of each line.
220      * @param fd The raw file descriptor that the dump is being sent to.
221      * @param writer A PrintWriter to which the dump is to be set.
222      * @param args Additional arguments to the dump request.
223      * @deprecated Use {@link #enableDebugLogging(boolean)} to understand the series of operations
224      * performed by LoaderManager.
225      */
226     @Deprecated
dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args)227     public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
228 
229     /**
230      * Control whether the framework's internal loader manager debugging
231      * logs are turned on.  If enabled, you will see output in logcat as
232      * the framework performs loader operations.
233      */
enableDebugLogging(boolean enabled)234     public static void enableDebugLogging(boolean enabled) {
235         LoaderManagerImpl.DEBUG = enabled;
236     }
237 
238     /**
239      * Returns true if any loaders managed are currently running and have not
240      * returned data to the application yet.
241      */
hasRunningLoaders()242     public boolean hasRunningLoaders() { return false; }
243 }
244