138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake/* 238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Copyright 2018 The Android Open Source Project 338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Licensed under the Apache License, Version 2.0 (the "License"); 538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * you may not use this file except in compliance with the License. 638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * You may obtain a copy of the License at 738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * http://www.apache.org/licenses/LICENSE-2.0 938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 1038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Unless required by applicable law or agreed to in writing, software 1138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * distributed under the License is distributed on an "AS IS" BASIS, 1238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * See the License for the specific language governing permissions and 1438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * limitations under the License. 1538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake */ 1638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.loader.app; 1838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 1938f4f4174d9cd53c553f14c19746500cb861b089Ian Lakeimport android.os.Bundle; 2038f4f4174d9cd53c553f14c19746500cb861b089Ian Lakeimport android.os.Looper; 2138f4f4174d9cd53c553f14c19746500cb861b089Ian Lakeimport android.util.Log; 2238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 2301b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.annotation.MainThread; 2401b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.annotation.NonNull; 2501b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.annotation.Nullable; 2601b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.collection.SparseArrayCompat; 2701b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.core.util.DebugUtils; 28ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.LifecycleOwner; 29ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.MutableLiveData; 30ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.Observer; 31ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.ViewModel; 32ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.ViewModelProvider; 33ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.lifecycle.ViewModelStore; 3401b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lakeimport androidx.loader.content.Loader; 3501b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lake 366160d5a551afe96c4180acf0454b5b4dbae89b9eAurimas Liutikasimport java.io.FileDescriptor; 376160d5a551afe96c4180acf0454b5b4dbae89b9eAurimas Liutikasimport java.io.PrintWriter; 386160d5a551afe96c4180acf0454b5b4dbae89b9eAurimas Liutikasimport java.lang.reflect.Modifier; 396160d5a551afe96c4180acf0454b5b4dbae89b9eAurimas Liutikas 4038f4f4174d9cd53c553f14c19746500cb861b089Ian Lakeclass LoaderManagerImpl extends LoaderManager { 4138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake static final String TAG = "LoaderManager"; 4238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake static boolean DEBUG = false; 4338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 4438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake /** 4538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Class which manages the state of a {@link Loader} and its associated 4638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * {@link LoaderCallbacks} 4738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 4838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * @param <D> Type of data the Loader handles 4938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake */ 5038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public static class LoaderInfo<D> extends MutableLiveData<D> 5138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake implements Loader.OnLoadCompleteListener<D> { 5238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 5338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final int mId; 5438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @Nullable Bundle mArgs; 5538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @NonNull Loader<D> mLoader; 5638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private LifecycleOwner mLifecycleOwner; 5738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private LoaderObserver<D> mObserver; 585404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake private Loader<D> mPriorLoader; 5938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 605404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake LoaderInfo(int id, @Nullable Bundle args, @NonNull Loader<D> loader, 615404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake @Nullable Loader<D> priorLoader) { 6238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mId = id; 6338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mArgs = args; 6438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader = loader; 655404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake mPriorLoader = priorLoader; 6638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.registerListener(id, this); 6738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 6838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 6938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 7038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake Loader<D> getLoader() { 7138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mLoader; 7238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 7338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 7438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 7538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake protected void onActive() { 7638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Starting: " + LoaderInfo.this); 7738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.startLoading(); 7838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 7938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 8038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 8138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake protected void onInactive() { 8238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Stopping: " + LoaderInfo.this); 8338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.stopLoading(); 8438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 8538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 8638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake /** 8738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Set the {@link LoaderCallbacks} to associate with this {@link Loader}. This 8838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * removes any existing {@link LoaderCallbacks}. 8938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 9038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * @param owner The lifecycle that should be used to start and stop the {@link Loader} 9138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * @param callback The new {@link LoaderCallbacks} to use 9238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * @return The {@link Loader} associated with this LoaderInfo 9338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake */ 9438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 9538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 9638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake Loader<D> setCallback(@NonNull LifecycleOwner owner, 9738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull LoaderCallbacks<D> callback) { 9838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderObserver<D> observer = new LoaderObserver<>(mLoader, callback); 9938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Add the new observer 10038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake observe(owner, observer); 10138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Loaders only support one observer at a time, so remove the current observer, if any 10238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (mObserver != null) { 10338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake removeObserver(mObserver); 10438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 10538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLifecycleOwner = owner; 10638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mObserver = observer; 10738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mLoader; 10838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 10938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 11038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake void markForRedelivery() { 11138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LifecycleOwner lifecycleOwner = mLifecycleOwner; 11238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderObserver<D> observer = mObserver; 11338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (lifecycleOwner != null && observer != null) { 11438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Removing and re-adding the observer ensures that the 11538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // observer is called again, even if they had already 11638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // received the current data 11750575bfebd6938a9914afc8cf05e2a5f9b1f57edIan Lake // Use super.removeObserver to avoid nulling out mLifecycleOwner & mObserver 11850575bfebd6938a9914afc8cf05e2a5f9b1f57edIan Lake super.removeObserver(observer); 11938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake observe(lifecycleOwner, observer); 12038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 12138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 12238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 12338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake boolean isCallbackWaitingForData() { 12438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake //noinspection SimplifiableIfStatement 12538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (!hasActiveObservers()) { 12638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // No active observers means no one is waiting for data 12738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return false; 12838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 12938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mObserver != null && !mObserver.hasDeliveredData(); 13038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 13138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 13238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 133ba069d50913c3fb250bb60ec310439db36895337Alan Viverette public void removeObserver(@NonNull Observer<? super D> observer) { 13438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake super.removeObserver(observer); 13538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Clear out our references when the observer is removed to avoid leaking 13638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLifecycleOwner = null; 13738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mObserver = null; 13838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 13938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 1405404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake /** 1415404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake * Destroys this LoaderInfo, its underlying {@link #getLoader() Loader}, and removes any 14201b544c7352c805d3c18f023b2eaeecb924ee1b3Ian Lake * existing {@link androidx.loader.app.LoaderManager.LoaderCallbacks}. 1435404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake * 1445404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake * @param reset Whether the LoaderCallbacks and Loader should be reset. 1455404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake * @return When reset is false, returns any Loader that still needs to be reset 1465404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake */ 14738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 1485404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake Loader<D> destroy(boolean reset) { 14938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Destroying: " + this); 15038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // First tell the Loader that we don't need it anymore 15138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.cancelLoad(); 15238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.abandon(); 15338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Then clean up the LoaderObserver 15438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderObserver<D> observer = mObserver; 15538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (observer != null) { 15638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake removeObserver(observer); 1575404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake if (reset) { 1585404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake observer.reset(); 1595404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake } 16038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 1615404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake // Finally, clean up the Loader 16238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.unregisterListener(this); 1635404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake if ((observer != null && !observer.hasDeliveredData()) || reset) { 1645404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake mLoader.reset(); 1655404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake return mPriorLoader; 1665404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake } 1675404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake return mLoader; 16838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 16938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 17038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 17138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void onLoadComplete(@NonNull Loader<D> loader, @Nullable D data) { 17238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, "onLoadComplete: " + this); 17302b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake if (Looper.myLooper() == Looper.getMainLooper()) { 17402b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake setValue(data); 17502b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake } else { 17602b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake // The Loader#deliverResult method that calls this should 17702b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake // only be called on the main thread, so this should never 17802b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake // happen, but we don't want to lose the data 17902b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake if (DEBUG) { 18002b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake Log.w(TAG, "onLoadComplete was incorrectly called on a " 18102b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake + "background thread"); 18202b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake } 18302b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake postValue(data); 18402b80098dcec67b9f0b92b1c87ec127b4a4844f1Ian Lake } 18538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 18638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 18738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 1885404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake public void setValue(D value) { 1895404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake super.setValue(value); 1905404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake // Now that the new data has arrived, we can reset any prior Loader 1915404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake if (mPriorLoader != null) { 1925404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake mPriorLoader.reset(); 1935404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake mPriorLoader = null; 1945404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake } 1955404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake } 1965404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake 1975404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake @Override 19838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public String toString() { 19938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake StringBuilder sb = new StringBuilder(64); 20038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append("LoaderInfo{"); 20138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(Integer.toHexString(System.identityHashCode(this))); 20238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(" #"); 20338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(mId); 20438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(" : "); 20538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake DebugUtils.buildShortClassTag(mLoader, sb); 20638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append("}}"); 20738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return sb.toString(); 20838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 20938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 210946ba810ddc84c105a657c671b2630bed6d15942Ian Lake @SuppressWarnings("deprecation") 21138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 21238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mId="); writer.print(mId); 21338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(" mArgs="); writer.println(mArgs); 21438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mLoader="); writer.println(mLoader); 21538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader.dump(prefix + " ", fd, writer, args); 21638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (mObserver != null) { 21738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mCallbacks="); writer.println(mObserver); 21838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mObserver.dump(prefix + " ", writer); 21938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 22038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mData="); writer.println( 22138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake getLoader().dataToString(getValue())); 22238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mStarted="); writer.println( 22338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake hasActiveObservers()); 22438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 22538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 22638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 22738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake /** 22838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * Encapsulates the {@link LoaderCallbacks} as a {@link Observer}. 22938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * 23038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * @param <D> Type of data the LoaderCallbacks handles 23138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake */ 23238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake static class LoaderObserver<D> implements Observer<D> { 23338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 23438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @NonNull Loader<D> mLoader; 23538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @NonNull LoaderCallbacks<D> mCallback; 23638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 23738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private boolean mDeliveredData = false; 23838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 23938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderObserver(@NonNull Loader<D> loader, @NonNull LoaderCallbacks<D> callback) { 24038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoader = loader; 24138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mCallback = callback; 24238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 24338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 24438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 24538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void onChanged(@Nullable D data) { 24638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) { 24738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake Log.v(TAG, " onLoadFinished in " + mLoader + ": " 24838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake + mLoader.dataToString(data)); 24938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 25038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mCallback.onLoadFinished(mLoader, data); 25138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mDeliveredData = true; 25238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 25338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 25438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake boolean hasDeliveredData() { 25538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mDeliveredData; 25638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 25738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 25838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 25938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake void reset() { 26038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (mDeliveredData) { 26138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Resetting: " + mLoader); 26238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mCallback.onLoaderReset(mLoader); 26338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 26438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 26538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 26638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 26738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public String toString() { 26838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mCallback.toString(); 26938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 27038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 27138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void dump(String prefix, PrintWriter writer) { 27238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print("mDeliveredData="); writer.println( 27338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mDeliveredData); 27438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 27538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 27638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 27738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake /** 27838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake * ViewModel responsible for retaining {@link LoaderInfo} instances across configuration changes 27938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake */ 28038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake static class LoaderViewModel extends ViewModel { 28138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() { 28238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 28338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 28438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @SuppressWarnings("unchecked") 28538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { 28638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return (T) new LoaderViewModel(); 28738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 28838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake }; 28938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 29038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 29138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake static LoaderViewModel getInstance(ViewModelStore viewModelStore) { 29238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return new ViewModelProvider(viewModelStore, FACTORY).get(LoaderViewModel.class); 29338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 29438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 29538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private SparseArrayCompat<LoaderInfo> mLoaders = new SparseArrayCompat<>(); 296afe28d91550483f9b7a82076a507151b4defd9baIan Lake private boolean mCreatingLoader = false; 297afe28d91550483f9b7a82076a507151b4defd9baIan Lake 298afe28d91550483f9b7a82076a507151b4defd9baIan Lake void startCreatingLoader() { 299afe28d91550483f9b7a82076a507151b4defd9baIan Lake mCreatingLoader = true; 300afe28d91550483f9b7a82076a507151b4defd9baIan Lake } 301afe28d91550483f9b7a82076a507151b4defd9baIan Lake 302afe28d91550483f9b7a82076a507151b4defd9baIan Lake boolean isCreatingLoader() { 303afe28d91550483f9b7a82076a507151b4defd9baIan Lake return mCreatingLoader; 304afe28d91550483f9b7a82076a507151b4defd9baIan Lake } 305afe28d91550483f9b7a82076a507151b4defd9baIan Lake 306afe28d91550483f9b7a82076a507151b4defd9baIan Lake void finishCreatingLoader() { 307afe28d91550483f9b7a82076a507151b4defd9baIan Lake mCreatingLoader = false; 308afe28d91550483f9b7a82076a507151b4defd9baIan Lake } 30938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 31038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake void putLoader(int id, @NonNull LoaderInfo info) { 31138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaders.put(id, info); 31238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 31338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 31438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @SuppressWarnings("unchecked") 31538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake <D> LoaderInfo<D> getLoader(int id) { 31638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mLoaders.get(id); 31738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 31838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 31938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake void removeLoader(int id) { 32038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaders.remove(id); 32138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 32238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 32338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake boolean hasRunningLoaders() { 32438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake int size = mLoaders.size(); 32538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake for (int index = 0; index < size; index++) { 32638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo info = mLoaders.valueAt(index); 32738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (info.isCallbackWaitingForData()) { 32838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return true; 32938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 33038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 33138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return false; 33238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 33338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 33438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake void markForRedelivery() { 33538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake int size = mLoaders.size(); 33638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake for (int index = 0; index < size; index++) { 33738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo info = mLoaders.valueAt(index); 33838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake info.markForRedelivery(); 33938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 34038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 34138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 34238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 34338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake protected void onCleared() { 34438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake super.onCleared(); 34538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake int size = mLoaders.size(); 34638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake for (int index = 0; index < size; index++) { 34738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo info = mLoaders.valueAt(index); 3485404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake info.destroy(true); 34938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 3500f4d973e9bb5a00727068f6a76338908c21902fdIan Lake mLoaders.clear(); 35138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 35238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 35338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 35438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (mLoaders.size() > 0) { 35538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.println("Loaders:"); 35638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake String innerPrefix = prefix + " "; 35738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake for (int i = 0; i < mLoaders.size(); i++) { 35838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo info = mLoaders.valueAt(i); 35938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i)); 36038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake writer.print(": "); writer.println(info.toString()); 36138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake info.dump(innerPrefix, fd, writer, args); 36238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 36338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 36438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 36538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 36638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 36738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @NonNull LifecycleOwner mLifecycleOwner; 36838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private final @NonNull LoaderViewModel mLoaderViewModel; 36938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 37038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderManagerImpl(@NonNull LifecycleOwner lifecycleOwner, 37138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull ViewModelStore viewModelStore) { 37238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLifecycleOwner = lifecycleOwner; 37338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaderViewModel = LoaderViewModel.getInstance(viewModelStore); 37438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 37538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 37638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 37738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 37838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake private <D> Loader<D> createAndInstallLoader(int id, @Nullable Bundle args, 3795404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake @NonNull LoaderCallbacks<D> callback, @Nullable Loader<D> priorLoader) { 380732fb271c18d4bed045f5d8284b46d428e7ad210Ian Lake LoaderInfo<D> info; 38138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake try { 382afe28d91550483f9b7a82076a507151b4defd9baIan Lake mLoaderViewModel.startCreatingLoader(); 38338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake Loader<D> loader = callback.onCreateLoader(id, args); 384f2b50d9efc9f0a438d6b1d85c463591398a2d306Ian Lake if (loader == null) { 385f2b50d9efc9f0a438d6b1d85c463591398a2d306Ian Lake throw new IllegalArgumentException("Object returned from onCreateLoader " 386f2b50d9efc9f0a438d6b1d85c463591398a2d306Ian Lake + "must not be null"); 387f2b50d9efc9f0a438d6b1d85c463591398a2d306Ian Lake } 38838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (loader.getClass().isMemberClass() 38938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake && !Modifier.isStatic(loader.getClass().getModifiers())) { 39038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalArgumentException("Object returned from onCreateLoader " 39138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake + "must not be a non-static inner member class: " 39238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake + loader); 39338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 3945404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake info = new LoaderInfo<>(id, args, loader, priorLoader); 39538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Created new loader " + info); 39638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaderViewModel.putLoader(id, info); 39738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } finally { 398afe28d91550483f9b7a82076a507151b4defd9baIan Lake mLoaderViewModel.finishCreatingLoader(); 39938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 400732fb271c18d4bed045f5d8284b46d428e7ad210Ian Lake return info.setCallback(mLifecycleOwner, callback); 40138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 40238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 40338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 40438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 40538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 40638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public <D> Loader<D> initLoader(int id, @Nullable Bundle args, 40738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull LoaderCallbacks<D> callback) { 408afe28d91550483f9b7a82076a507151b4defd9baIan Lake if (mLoaderViewModel.isCreatingLoader()) { 40938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("Called while creating a loader"); 41038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 41138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (Looper.getMainLooper() != Looper.myLooper()) { 41238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("initLoader must be called on the main thread"); 41338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 41438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 41538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo<D> info = mLoaderViewModel.getLoader(id); 41638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 41738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); 41838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 41938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (info == null) { 42038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // Loader doesn't already exist; create. 4215404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake return createAndInstallLoader(id, args, callback, null); 42238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } else { 42338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); 42438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return info.setCallback(mLifecycleOwner, callback); 42538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 42638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 42738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 42838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 42938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull 43038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 43138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public <D> Loader<D> restartLoader(int id, @Nullable Bundle args, 43238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @NonNull LoaderCallbacks<D> callback) { 433afe28d91550483f9b7a82076a507151b4defd9baIan Lake if (mLoaderViewModel.isCreatingLoader()) { 43438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("Called while creating a loader"); 43538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 43638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (Looper.getMainLooper() != Looper.myLooper()) { 43738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("restartLoader must be called on the main thread"); 43838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 43938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 44038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args); 4415404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake LoaderInfo<D> info = mLoaderViewModel.getLoader(id); 4425404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake Loader<D> priorLoader = null; 4435404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake if (info != null) { 4445404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake priorLoader = info.destroy(false); 4455404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake } 44638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake // And create a new Loader 4475404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake return createAndInstallLoader(id, args, callback, priorLoader); 44838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 44938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 45038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @MainThread 45138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 45238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void destroyLoader(int id) { 453afe28d91550483f9b7a82076a507151b4defd9baIan Lake if (mLoaderViewModel.isCreatingLoader()) { 45438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("Called while creating a loader"); 45538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 45638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (Looper.getMainLooper() != Looper.myLooper()) { 45738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("destroyLoader must be called on the main thread"); 45838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 45938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 46038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id); 46138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo info = mLoaderViewModel.getLoader(id); 46238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake if (info != null) { 4635404d815b5a1cc57d7b1dc6c1f89627f627e76eeIan Lake info.destroy(true); 46438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaderViewModel.removeLoader(id); 46538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 46638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 46738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 46838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Nullable 46938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 47038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public <D> Loader<D> getLoader(int id) { 471afe28d91550483f9b7a82076a507151b4defd9baIan Lake if (mLoaderViewModel.isCreatingLoader()) { 47238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake throw new IllegalStateException("Called while creating a loader"); 47338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 47438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 47538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake LoaderInfo<D> info = mLoaderViewModel.getLoader(id); 47638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return info != null ? info.getLoader() : null; 47738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 47838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 479afe28d91550483f9b7a82076a507151b4defd9baIan Lake @Override 480afe28d91550483f9b7a82076a507151b4defd9baIan Lake public void markForRedelivery() { 48138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaderViewModel.markForRedelivery(); 48238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 48338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 48438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 48538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public String toString() { 48638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake StringBuilder sb = new StringBuilder(128); 48738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append("LoaderManager{"); 48838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(Integer.toHexString(System.identityHashCode(this))); 48938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append(" in "); 49038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake DebugUtils.buildShortClassTag(mLifecycleOwner, sb); 49138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake sb.append("}}"); 49238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return sb.toString(); 49338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 49438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 495946ba810ddc84c105a657c671b2630bed6d15942Ian Lake @Deprecated 49638f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 49738f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 49838f4f4174d9cd53c553f14c19746500cb861b089Ian Lake mLoaderViewModel.dump(prefix, fd, writer, args); 49938f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 50038f4f4174d9cd53c553f14c19746500cb861b089Ian Lake 50138f4f4174d9cd53c553f14c19746500cb861b089Ian Lake @Override 50238f4f4174d9cd53c553f14c19746500cb861b089Ian Lake public boolean hasRunningLoaders() { 50338f4f4174d9cd53c553f14c19746500cb861b089Ian Lake return mLoaderViewModel.hasRunningLoaders(); 50438f4f4174d9cd53c553f14c19746500cb861b089Ian Lake } 50538f4f4174d9cd53c553f14c19746500cb861b089Ian Lake} 506