When identifying Loaders in your LoaderManager, you use unique ids. I'm asking about how unique those ids have to be.
Does every activity and fragment have its own LoaderManager? Do fragments use the LoaderManager of the Activity they're attached to? Is there only one LoaderManager that the application owns?
Bonus points if you can tell me how it's possible to change which LoaderManager you're using. If I want every fragment in my Activity to use the same LoaderManager (some of them are pulling the same data and sharing Loaders would be nice), is that possible?
Simply stated, the LoaderManager is responsible for managing one or more Loader s associated with an Activity or Fragment . Each Activity and each Fragment has exactly one LoaderManager instance that is in charge of starting, stopping, retaining, restarting, and destroying its Loader s.
A CursorLoader is a specialized member of Android's loader framework specifically designed to handle cursors. In a typical implementation, a CursorLoader uses a ContentProvider to run a query against a database, then returns the cursor produced from the ContentProvider back to an activity or fragment.
Loaders persist and cache results across configuration changes to prevent duplicate queries. Loaders can implement an observer to monitor for changes in the underlying data source. For example, CursorLoader automatically registers a ContentObserver to trigger a reload when data changes.
I'm currently porting my application to the android compatibility package (mainly for CursorLoader and Fragments). I'm currently trying to share a CursorLoader between two fragments to spare a query to my ContentProvider. Welcome to my world! ;)
A simple use case:
− DummyActivity extends FragmentActivity / Log.d(Constants.LOGTAG, "DummyActivity.onCreate " + getSupportLoaderManager().toString());
− DataFragment extends Fragment implements LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "DataFragment.onCreate " + getLoaderManager().toString());
− ReportFragment extends Fragment implements LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "ReportFragment.onCreate " + getLoaderManager().toString());
DummyActivity instanciates the DataFragment and the later instanciates the ReportFragment. The logcat output shows differents addresses for each LoaderManager. As a first conclusion, each Fragment seems to have a proper LoaderManager…
I will continue and update if I can answer to your (our ;) ) question. If you have made any progress, please share your valuable knowledge.
Update:
My assumption is that the loader ids are only associated with a local scope of a LoaderManager for a specific fragment to enable several local loaders to be associated with the fragment (so you can return a different loader in onCreateLoader based on the id int arg and the initLoader calls).
So far I managed to "reuse" a Loader (… or not):
− First, I have enabled LoaderManager debugging with getSupportLoaderManager().enableDebugLogging(true);
in the DummyActivity onCreate
method.
− Then I have called getActivity().getSupportLoaderManager().initLoader(78, null, this);
from the onCreate
methods of both DataFragment and ReportFragment.
− DataFragment exposes the CursorLoader created by the onCreateLoader
method via a setter on a mCursorLoader private member.
− The ReportFragment onCreateLoader
returns the DataFragment CursorLoader (after retrieving the Fragment with findFragmentByTag
).
The filtered (and slightly obfuscated) logcat output:
DummyApp D DummyActivity.onCreate
DummyApp D DataFragment.newInstance
DummyApp D ReportFragment.newInstance
DummyApp D DataFragment.onCreate
LoaderManager V initLoader in LoaderManager{405a19d0 in SpecificAction{4059ee98}}: args=null
DummyApp D DataFragment.onCreateLoader
LoaderManager V Created new loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyApp D DataFragment.onCreate
DummyApp D DataFragment.onActivityCreated
DummyApp D ReportFragment.onCreate
LoaderManager V initLoader in LoaderManager{405a19d0 in DummyActivity{4059ee98}}: args=null
LoaderManager V Re-using existing loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyApp D SpecificActionReportFragment.onCreate
DummyApp D SpecificActionReportFragment.onActivityCreated
LoaderManager V Starting in LoaderManager{405a19d0 in DummyActivity{4059ee98}}
LoaderManager V Starting: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyProvider D query called
DummyProvider D […]
DummyProvider D [end of query]
LoaderManager V onLoadComplete: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
LoaderManager V onLoadFinished in CursorLoader{405a22e0 id=78}: CursorWrapperInner{405afb20}
DummyApp D ReportFragment.onLoadFinished
DummyApp D ReportFragment.displayActionReport
DummyApp D DummyActivity.setReportViewsVisibility
DummyApp D ReportFragment.setSaveReportImageViewVisibility
The two fragments are added from the DummyActivity onCreate
method (different from the described use case, but that changes nothing to the issue we are working on). Unfortunately, the loader is reassigned to the latest fragment calling it (here ReportFragment)… and DataFragment.onLoadFinished is never called. As a consequence, the ReportFragment looks good but the DataFragment is not up-to-date since the update is called from the onLoadFinished
of this class.
I assume that there is an underlying unregister call then a register call on the CursorLoader.
To be continued…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With