| /* |
| * 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. |
| */ |
| 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; } |
| } |