LoaderManagerImpl.java revision ac5fe7c617c66850fff75a9fce9979c6e5674b0f
1707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet/* 2707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Copyright 2018 The Android Open Source Project 3707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 4707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License"); 5707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * you may not use this file except in compliance with the License. 6707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * You may obtain a copy of the License at 7707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 8707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * http://www.apache.org/licenses/LICENSE-2.0 9707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * 10707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software 11707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS, 12707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * See the License for the specific language governing permissions and 14707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet * limitations under the License. 15707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet */ 16707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 173ced3cfd5b8f22b632c35f24e585c4847383b195David Grosspackage androidx.loader.app; 18707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 193ced3cfd5b8f22b632c35f24e585c4847383b195David Grossimport android.arch.lifecycle.LifecycleOwner; 20707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.arch.lifecycle.MutableLiveData; 2183e24dc4706a5b7089881a55daf05b3924fab3b7David Grossimport android.arch.lifecycle.Observer; 22707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.arch.lifecycle.ViewModel; 23707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.arch.lifecycle.ViewModelProvider; 24707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.arch.lifecycle.ViewModelStore; 25707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.os.Bundle; 26707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.os.Looper; 27689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerimport androidx.annotation.MainThread; 28389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletimport androidx.annotation.NonNull; 29689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerimport androidx.annotation.Nullable; 30689d892203c06c66c7bb2e374462a8434e40b75fMichael Butlerimport androidx.loader.content.Loader; 31707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport androidx.core.util.DebugUtils; 32707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport androidx.collection.SparseArrayCompat; 33707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouilletimport android.util.Log; 34389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 35389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletimport java.io.FileDescriptor; 36389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletimport java.io.PrintWriter; 37389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletimport java.lang.reflect.Modifier; 38389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 39389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouilletclass LoaderManagerImpl extends LoaderManager { 40389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet static final String TAG = "LoaderManager"; 41389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet static boolean DEBUG = false; 42a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet 43389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet /** 44389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * Class which manages the state of a {@link Loader} and its associated 45389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * {@link LoaderCallbacks} 46389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * 47389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * @param <D> Type of data the Loader handles 48389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet */ 49389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet public static class LoaderInfo<D> extends MutableLiveData<D> 50389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet implements Loader.OnLoadCompleteListener<D> { 51389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 52389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet private final int mId; 53389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet private final @Nullable Bundle mArgs; 54389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet private final @NonNull Loader<D> mLoader; 55389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet private LifecycleOwner mLifecycleOwner; 56389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet private LoaderObserver<D> mObserver; 57389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 58389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet LoaderInfo(int id, @Nullable Bundle args, @NonNull Loader<D> loader) { 5996811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mId = id; 6096811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mArgs = args; 6196811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mLoader = loader; 6296811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mLoader.registerListener(id, this); 6396811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross } 6496811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross 6596811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross @NonNull 6696811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross Loader<D> getLoader() { 6796811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross return mLoader; 68389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 69389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 70389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet @Override 71389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet protected void onActive() { 72389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (DEBUG) Log.v(TAG, " Starting: " + LoaderInfo.this); 73d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet mLoader.startLoading(); 74389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet } 75389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 763ced3cfd5b8f22b632c35f24e585c4847383b195David Gross @Override 77389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet protected void onInactive() { 78389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet if (DEBUG) Log.v(TAG, " Stopping: " + LoaderInfo.this); 79389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mLoader.stopLoading(); 80d2d0c031c43e8e5aafc75e8a652d79bcc2aaca99Jean-Luc Brouillet } 81389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 82389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet /** 83389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * Set the {@link LoaderCallbacks} to associate with this {@link Loader}. This 84389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * removes any existing {@link LoaderCallbacks}. 85389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet * 863ced3cfd5b8f22b632c35f24e585c4847383b195David Gross * @param owner The lifecycle that should be used to start and stop the {@link Loader} 8783e24dc4706a5b7089881a55daf05b3924fab3b7David Gross * @param callback The new {@link LoaderCallbacks} to use 881f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross * @return The {@link Loader} associated with this LoaderInfo 8983e24dc4706a5b7089881a55daf05b3924fab3b7David Gross */ 9083e24dc4706a5b7089881a55daf05b3924fab3b7David Gross @MainThread 9183e24dc4706a5b7089881a55daf05b3924fab3b7David Gross @NonNull 923ced3cfd5b8f22b632c35f24e585c4847383b195David Gross Loader<D> setCallback(@NonNull LifecycleOwner owner, 93707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet @NonNull LoaderCallbacks<D> callback) { 94707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LoaderObserver<D> observer = new LoaderObserver<>(mLoader, callback); 953ced3cfd5b8f22b632c35f24e585c4847383b195David Gross // Add the new observer 96e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet observe(owner, observer); 97707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Loaders only support one observer at a time, so remove the current observer, if any 98707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (mObserver != null) { 993ced3cfd5b8f22b632c35f24e585c4847383b195David Gross removeObserver(mObserver); 100707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 101707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mLifecycleOwner = owner; 102e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet mObserver = observer; 103e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet return mLoader; 104e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 105e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet 106e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet void markForRedelivery() { 107e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet LifecycleOwner lifecycleOwner = mLifecycleOwner; 108e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet LoaderObserver<D> observer = mObserver; 109e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (lifecycleOwner != null && observer != null) { 110e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet // Removing and re-adding the observer ensures that the 111e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet // observer is called again, even if they had already 112e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet // received the current data 113389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet // Use super.removeObserver to avoid nulling out mLifecycleOwner & mObserver 114e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet super.removeObserver(observer); 115707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet observe(lifecycleOwner, observer); 116707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 1173ced3cfd5b8f22b632c35f24e585c4847383b195David Gross } 118e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet 11996811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross boolean isCallbackWaitingForData() { 12096811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross //noinspection SimplifiableIfStatement 1218b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (!hasActiveObservers()) { 1228b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // No active observers means no one is waiting for data 1233ced3cfd5b8f22b632c35f24e585c4847383b195David Gross return false; 1248b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1258b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return mObserver != null && !mObserver.hasDeliveredData(); 1268b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 127105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang 128105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang @Override 129105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang public void removeObserver(@NonNull Observer<D> observer) { 130e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet super.removeObserver(observer); 131389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet // Clear out our references when the observer is removed to avoid leaking 132389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mLifecycleOwner = null; 133389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet mObserver = null; 134707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 135707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 1363ced3cfd5b8f22b632c35f24e585c4847383b195David Gross @MainThread 137e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet void destroy() { 138707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (DEBUG) Log.v(TAG, " Destroying: " + this); 139707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // First tell the Loader that we don't need it anymore 1403ced3cfd5b8f22b632c35f24e585c4847383b195David Gross mLoader.cancelLoad(); 141707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mLoader.abandon(); 142707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet // Then clean up the LoaderObserver 143e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet LoaderObserver<D> observer = mObserver; 144e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet if (observer != null) { 145e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet removeObserver(observer); 146e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet observer.reset(); 147e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 148e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet // Finally, send the reset to the Loader 149e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet mLoader.unregisterListener(this); 150e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet mLoader.reset(); 151e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } 152e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet 153e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet @Override 154e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet public void onLoadComplete(@NonNull Loader<D> loader, @Nullable D data) { 155707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (DEBUG) Log.v(TAG, "onLoadComplete: " + this); 156707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (Looper.myLooper() == Looper.getMainLooper()) { 1573ced3cfd5b8f22b632c35f24e585c4847383b195David Gross setValue(data); 158e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet } else { 15996811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross // The Loader#deliverResult method that calls this should 16096811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross // only be called on the main thread, so this should never 1618b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // happen, but we don't want to lose the data 1628b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (DEBUG) { 1633ced3cfd5b8f22b632c35f24e585c4847383b195David Gross Log.w(TAG, "onLoadComplete was incorrectly called on a " 1648b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet + "background thread"); 1658b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 1668b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet postValue(data); 167105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang } 168105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang } 169105807d963d969197fe78185ed588bfad3dc0ea5Miao Wang 170e127e49e67b53c96eb79f6a9c58f956ad4761227Jean-Luc Brouillet @Override 171389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet public String toString() { 172389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet StringBuilder sb = new StringBuilder(64); 173389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet sb.append("LoaderInfo{"); 174707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append(Integer.toHexString(System.identityHashCode(this))); 175707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append(" #"); 176033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler sb.append(mId); 177033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler sb.append(" : "); 178425b2594c76e934dfdbc93209253e3c189571149David Gross DebugUtils.buildShortClassTag(mLoader, sb); 179707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append("}}"); 180707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return sb.toString(); 181f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni } 182f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni 183f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 1848b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet writer.print(prefix); writer.print("mId="); writer.print(mId); 185389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet writer.print(" mArgs="); writer.println(mArgs); 1863ced3cfd5b8f22b632c35f24e585c4847383b195David Gross writer.print(prefix); writer.print("mLoader="); writer.println(mLoader); 187707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mLoader.dump(prefix + " ", fd, writer, args); 188707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (mObserver != null) { 189707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet writer.print(prefix); writer.print("mCallbacks="); writer.println(mObserver); 190f1817c663af4f22bc089ef82cd50df4186422c42Yang Ni mObserver.dump(prefix + " ", writer); 1918b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 192389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet writer.print(prefix); writer.print("mData="); writer.println( 1933ced3cfd5b8f22b632c35f24e585c4847383b195David Gross getLoader().dataToString(getValue())); 194707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet writer.print(prefix); writer.print("mStarted="); writer.println( 195707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet hasActiveObservers()); 196707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 197707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 1981f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 1991f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross /** 200b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross * Encapsulates the {@link LoaderCallbacks} as a {@link Observer}. 201b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross * 202b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross * @param <D> Type of data the LoaderCallbacks handles 203b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross */ 2041f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross static class LoaderObserver<D> implements Observer<D> { 205891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 206891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross private final @NonNull Loader<D> mLoader; 207891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross private final @NonNull LoaderCallbacks<D> mCallback; 208891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 209891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross private boolean mDeliveredData = false; 210891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 211891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross LoaderObserver(@NonNull Loader<D> loader, @NonNull LoaderCallbacks<D> callback) { 212891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mLoader = loader; 213891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mCallback = callback; 214891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 215891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 216891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross @Override 217891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross public void onChanged(@Nullable D data) { 218891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross if (DEBUG) { 219891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross Log.v(TAG, " onLoadFinished in " + mLoader + ": " 220891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross + mLoader.dataToString(data)); 221b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 222891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mCallback.onLoadFinished(mLoader, data); 223891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mDeliveredData = true; 224891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 225891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 226891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross boolean hasDeliveredData() { 227891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross return mDeliveredData; 228891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 229891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 230891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross @MainThread 231891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross void reset() { 232891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross if (mDeliveredData) { 233033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (DEBUG) Log.v(TAG, " Resetting: " + mLoader); 234891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mCallback.onLoaderReset(mLoader); 235891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 236891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 237033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 238033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @Override 239891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross public String toString() { 240891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross return mCallback.toString(); 241b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 2421f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 2431f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross public void dump(String prefix, PrintWriter writer) { 2441f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross writer.print(prefix); writer.print("mDeliveredData="); writer.println( 245ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet mDeliveredData); 246ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet } 2471f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross } 2481f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 249ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet /** 250ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet * ViewModel responsible for retaining {@link LoaderInfo} instances across configuration changes 251ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet */ 2521f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross static class LoaderViewModel extends ViewModel { 253ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() { 254ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet @NonNull 2551f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross @Override 256b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross @SuppressWarnings("unchecked") 257b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { 258b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross return (T) new LoaderViewModel(); 259033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } 260ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet }; 261ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet 262ef22aa5727b96e9a0863ef71cfbe3dbdac339408Jean-Luc Brouillet @NonNull 2631f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross static LoaderViewModel getInstance(ViewModelStore viewModelStore) { 264b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross return new ViewModelProvider(viewModelStore, FACTORY).get(LoaderViewModel.class); 265b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 266b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross 267b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross private SparseArrayCompat<LoaderInfo> mLoaders = new SparseArrayCompat<>(); 268033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler private boolean mCreatingLoader = false; 269707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 270707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet void startCreatingLoader() { 271707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet mCreatingLoader = true; 2728b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 273b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross 274b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross boolean isCreatingLoader() { 2758b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return mCreatingLoader; 276707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 2778b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 2788b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet void finishCreatingLoader() { 2798b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mCreatingLoader = false; 2808b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 2818b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 2828b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet void putLoader(int id, @NonNull LoaderInfo info) { 2838b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mLoaders.put(id, info); 2848b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 2858b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 2868b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet @SuppressWarnings("unchecked") 287707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet <D> LoaderInfo<D> getLoader(int id) { 2883ced3cfd5b8f22b632c35f24e585c4847383b195David Gross return mLoaders.get(id); 289707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 290707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet 291707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet void removeLoader(int id) { 2928b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mLoaders.remove(id); 2938b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 294389f26c7c442c37994db9f43d013fe3953c9353cJean-Luc Brouillet 2958b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet boolean hasRunningLoaders() { 2968b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet int size = mLoaders.size(); 297707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet for (int index = 0; index < size; index++) { 298707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet LoaderInfo info = mLoaders.valueAt(index); 299707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (info.isCallbackWaitingForData()) { 3008b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return true; 301a4e2ee81d015b5e26897d18b18dd50044faba62fJean-Luc Brouillet } 3028b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3038b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet return false; 3048b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 3058b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 3068b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet void markForRedelivery() { 3078b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet int size = mLoaders.size(); 3088b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet for (int index = 0; index < size; index++) { 309b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross LoaderInfo info = mLoaders.valueAt(index); 310b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross info.markForRedelivery(); 311b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 312b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 313891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 314891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross @Override 315b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross protected void onCleared() { 316b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross super.onCleared(); 317b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross int size = mLoaders.size(); 318b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross for (int index = 0; index < size; index++) { 319b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross LoaderInfo info = mLoaders.valueAt(index); 320b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross info.destroy(); 321b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 322891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross mLoaders.clear(); 323891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 324891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 325891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 326891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross if (mLoaders.size() > 0) { 327891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross writer.print(prefix); writer.println("Loaders:"); 328891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross String innerPrefix = prefix + " "; 329891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross for (int i = 0; i < mLoaders.size(); i++) { 330891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross LoaderInfo info = mLoaders.valueAt(i); 331891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross writer.print(prefix); writer.print(" #"); writer.print(mLoaders.keyAt(i)); 332891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross writer.print(": "); writer.println(info.toString()); 333891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross info.dump(innerPrefix, fd, writer, args); 334891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 335891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 336891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 337891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross } 338891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 339891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross private final @NonNull LifecycleOwner mLifecycleOwner; 340891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross private final @NonNull LoaderViewModel mLoaderViewModel; 341891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross 342891b10f7048c62a37a74c4b570be220089dfd55eDavid Gross LoaderManagerImpl(@NonNull LifecycleOwner lifecycleOwner, 34396811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross @NonNull ViewModelStore viewModelStore) { 34496811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mLifecycleOwner = lifecycleOwner; 34596811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross mLoaderViewModel = LoaderViewModel.getInstance(viewModelStore); 34696811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross } 34796811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross 34896811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross @MainThread 34996811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross @NonNull 35096811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross private <D> Loader<D> createAndInstallLoader(int id, @Nullable Bundle args, 35196811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross @NonNull LoaderCallbacks<D> callback) { 35296811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross LoaderInfo<D> info; 35396811e2b1347889a25bd9686f47ca3cbf061fb1bDavid Gross try { 354033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler mLoaderViewModel.startCreatingLoader(); 355b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross Loader<D> loader = callback.onCreateLoader(id, args); 356033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (loader.getClass().isMemberClass() 357b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross && !Modifier.isStatic(loader.getClass().getModifiers())) { 358033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler throw new IllegalArgumentException("Object returned from onCreateLoader " 359b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross + "must not be a non-static inner member class: " 360b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross + loader); 361b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 362033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler info = new LoaderInfo<>(id, args, loader); 363b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross if (DEBUG) Log.v(TAG, " Created new loader " + info); 364b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross mLoaderViewModel.putLoader(id, info); 365033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } finally { 366425b2594c76e934dfdbc93209253e3c189571149David Gross mLoaderViewModel.finishCreatingLoader(); 367b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 3681f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross return info.setCallback(mLifecycleOwner, callback); 369b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross } 3701f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 3711f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross @MainThread 3721f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross @NonNull 3731f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross @Override 374033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler public <D> Loader<D> initLoader(int id, @Nullable Bundle args, 375033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @NonNull LoaderCallbacks<D> callback) { 376033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (mLoaderViewModel.isCreatingLoader()) { 377033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler throw new IllegalStateException("Called while creating a loader"); 378033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } 379033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (Looper.getMainLooper() != Looper.myLooper()) { 3805f916fc9a7ae95f172492bdfe5344c37beff3a6fMichael Butler throw new IllegalStateException("initLoader must be called on the main thread"); 381033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } 3821f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross 383033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler LoaderInfo<D> info = mLoaderViewModel.getLoader(id); 384033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 385033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args); 386033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 3871f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross if (info == null) { 3881f4381539b7e89c42336ee7cd1addb9a4c317b34David Gross // Loader doesn't already exist; create. 389707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet return createAndInstallLoader(id, args, callback); 390707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } else { 391e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross if (DEBUG) Log.v(TAG, " Re-using existing loader " + info); 392e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross return info.setCallback(mLifecycleOwner, callback); 393e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross } 394e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross } 395e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross 396e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross @MainThread 3978b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet @NonNull 398e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross @Override 399707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet public <D> Loader<D> restartLoader(int id, @Nullable Bundle args, 400707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet @NonNull LoaderCallbacks<D> callback) { 401707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (mLoaderViewModel.isCreatingLoader()) { 402e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross throw new IllegalStateException("Called while creating a loader"); 403707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 404707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (Looper.getMainLooper() != Looper.myLooper()) { 405707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet throw new IllegalStateException("restartLoader must be called on the main thread"); 406707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 4078b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 408e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args); 4098b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // Destroy any existing Loader 4108b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet destroyLoader(id); 4118b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet // And create a new Loader 4122150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet return createAndInstallLoader(id, args, callback); 413e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross } 4142150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet 4152150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet @MainThread 4162150f1d186b2854fb5aa609594be12a667f845f0Jean-Luc Brouillet @Override 4178b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet public void destroyLoader(int id) { 4188b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (mLoaderViewModel.isCreatingLoader()) { 419707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet throw new IllegalStateException("Called while creating a loader"); 420e413eef7e5f790acdb8e5d07cacfee9afab6f7beDavid Gross } 421707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet if (Looper.getMainLooper() != Looper.myLooper()) { 422707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet throw new IllegalStateException("destroyLoader must be called on the main thread"); 4238b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet } 4248b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet 4258b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id); 4268b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet LoaderInfo info = mLoaderViewModel.getLoader(id); 4278b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet if (info != null) { 4288b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet info.destroy(); 4298b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet mLoaderViewModel.removeLoader(id); 430707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet } 431033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } 432033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 433033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @Nullable 434033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @Override 435033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler public <D> Loader<D> getLoader(int id) { 436033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler if (mLoaderViewModel.isCreatingLoader()) { 437033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler throw new IllegalStateException("Called while creating a loader"); 438689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 439033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 440689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler LoaderInfo<D> info = mLoaderViewModel.getLoader(id); 441033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler return info != null ? info.getLoader() : null; 442689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 443b26049114bc4c64e6bea3a5d5d129fcaec8e69b6David Gross 4443ced3cfd5b8f22b632c35f24e585c4847383b195David Gross @Override 445033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler public void markForRedelivery() { 446033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler mLoaderViewModel.markForRedelivery(); 447689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 448689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 449033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @Override 450689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler public String toString() { 451033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler StringBuilder sb = new StringBuilder(128); 452707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append("LoaderManager{"); 453707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append(Integer.toHexString(System.identityHashCode(this))); 454707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet sb.append(" in "); 455707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet DebugUtils.buildShortClassTag(mLifecycleOwner, sb); 456689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler sb.append("}}"); 457689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return sb.toString(); 458033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler } 459033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler 460033b8a6ce8ebd2a01ecccc6bae96d0fff8d4964eMichael Butler @Override 461689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 462689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler mLoaderViewModel.dump(prefix, fd, writer, args); 463689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 464689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler 465707dbd2d55f5dacf78ffb3ad7c8b3f37c2e9d758Jean-Luc Brouillet @Override 466689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler public boolean hasRunningLoaders() { 467689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler return mLoaderViewModel.hasRunningLoaders(); 468689d892203c06c66c7bb2e374462a8434e40b75fMichael Butler } 4698b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet} 4708b99bb1d98a42b67ba1c00e12c7abb3708cf7c05Jean-Luc Brouillet