Loaders
Introduced in Android 3.0. In Activity
and Fragment
, Loaders
data can be easily loaded using the. For Activity
Fragment
An introduction, you can refer to the official documents of my translation:
" Activities
"
" Fragments
"
This article will introduce the Loaders API, loaders startup, restart, Loaders Manager and other content, if you need to access the official text of loaders, you can click on this link: " Loaders
.
Loaders
The loaders has the following characteristics:
It applies to any Activity
and Fragment
;
It uses the asynchronous loading method (asynchronous loading of data);
When the content changes, it listens to the change of the data source and transmits the new result;
When the system configuration changes, when the data is overloaded, it automatically re-connects Loader
the latest cursor (automatically reconnect to the last loader's cursor). Therefore, there is no need to requery the data.
Loader
API Overview (Loader API Summary)
Loader's main API is summarized below:
class/interface |
description |
loadermanager |
This is an abstract class for binding with an activity or fragment, To manage several loader instances, which can help an application easily handle long operations in the activity or fragment life cycle (manage longer-running operations in conjunction with the Activity or Fragment lifecycle); The most common usage of this abstract class is to work with Cursorloader, and of course the application is free to write the corresponding loaders for other types of data. |
loadermanager.loadercallbacks |
one with loadermanager the callback interface for the interaction, such as the Oncreateloader () method can be called to create a loader instance. |
loader |
Cursorloader is a more common implementation class. However, you can also customize the implementation class yourself. Loader is dynamic and can listen to changes in the data source in real time. |
asynctaskloader |
|
cursorloader |
This is a asynctaskloader Subclass that can query and return a reference to a cursor object from Contentresolver. |
In the above table, LoaderManager
is a base class for creating loader objects Loader
, and a basic class for implementing different types of loader, such as CursorLoader
a loader implementation class.
The following describes how to use these classes.
Using in the application
Loaders
(Using loaders in an application)
In one application, Loader
the following scenarios are used:
Activity
or Fragment
medium;
LoaderManager
Example (an instance of the LoaderManager
);
Use CursorLoader
ContentProvider
the data provided in the load. You can also inherit Loader
or AsyncTaskLoader
load other types of data;
Implements the LoaderManager.LoaderCallbacks
callback interface. In the callback, you can create a new loader instance, or you can manage an existing Loader
instance.
Determines how the display of the loaded data is laid out, such as SimpleCursorAdapter
.
When you load a data source, such as CursorLoader
.
Create
Loader
Object (starting a Loader)
LoaderManager
Responsible for Activity
Fragment
creating one or more instances in or Loader
. each one Activity
or both Fragment
holds and holds only one LoaderManager
instance .
In general, create an Activity
instance in the onCreate()
callback method, or in the Fragment
onActivityCreated()
callback method Loader
:
// Prepare the loader. with an existing one,//ornew one.getLoaderManager().initLoader(0nullthis);
initLoader()
The parameters of the method are as follows:
Parameter 1 ( int
): The ID of an loader instance is identified, and the ID is 0 in the example;
Parameter 2 ( Bundle
): an optional parameter for building a loader instance, null in the example;
Parameter 3 ( LoaderManager.LoaderCallbacks
): LoaderManager
called by to notify the loader event. In the example, the class implements the LoaderManager.LoaderCallbacks
interface, so it is this
.
Calling initLoader()
a method ensures that a loader instance is created and activated (a loader is initialized and active). This produces two kinds of results:
If the ID specified for loader already exists, the existing loader will be reused (the last created loader is reused);
If the ID specified for loader does not exist, the initLoader()
method fires the callback method in (triggers), LoaderManager.LoaderCallbacks
onCreateLoader()
where you need to instantiate the loader object and return the object.
Regardless of the above situation, the object that implements the Loadermanager.loadercallbacks interface will be associated with the loader. And when the state of the loader changes, the method in the callback interface is called back. callback method, requires that the bound loader has been initialized and the data is loaded, and then the system immediately callbacks onLoadFinished()
the method ( initLoader()
callback (during) when executing the method initLoader()
).
Although a initLoader()
method returns a Loader
reference to an object or its subclass object, the program does not need to hold this reference (you don't need to capture a reference to it) because it LoaderManager
automatically manages the lifecycle of all created loader, The LoaderManager
load is started or stopped when needed, and the data associated with loader is obtained for the state of the loader that governs it. This means that you do not need to interact directly with loaders, but in most cases, when an event occurs, you need to LoaderManager.LoaderCallbacks
manage the loading process using the callback method in the intervene. Loading process when particular events occur).
Restart Loader (restarting a Loader)
As mentioned above, initLoader()
when called, if the passed ID value already exists, the loader is reused and a new loader is created if it does not exist. Sometimes, however, you want to discard the old data and restart it (sometimes you want to discard your older and start over).
In order to discard the old data, you can call the restartLoader()
method, for example, when the content of the user query changes, loader need to restart, update the search filter, and make a new query (can use the revised search filter to do a new query). As shown in the following example:
publicbooleanonQueryTextChanged(String newText) { // Called when the action bar search text has changed. Update // the search filter, and restart the loader to do a new query // with this filter. null; getLoaderManager().restartLoader(0nullthis); returntrue;}
Using the Loadermanager callback (using the Loadermanager callbacks)
Loadermanager.loadercallbacks is a callback interface that allows clients to interact with each other LoaderManager
conveniently (lets a client interact with the Loadermanager).
When in the Stop state, Loader (in particular CursorLoader
) wants to keep their data from being lost. This requires that onStart()
data is not lost through activity or fragment and onStop()
methods (keep their data across the activity or fragment ' s onStop () and OnStart () meth ODS). So when the user returns to the app, you don't have to wait for the data to reload. You can LoaderManager.LoaderCallbacks
monitor when the new loader was created, or when loader stopped using the data (when to create a new loader, and to tell the application when it was time to Sto P using a loader ' s data).
The callback interface LoaderManager.LoaderCallbacks
contains the following methods:
onCreateLoader()
: Initializes a new loader and assigns an ID;
onLoadFinished()
: When a loader that has been created stops loading, the method is recalled;
onLoaderReset()
: The method is called back when a previously created loader is restarted (when the data is not available).
Each callback method is described in detail below:
When you need to get an loader instance (as obtained through a initLoader()
method), the method queries whether the newly created loader ID is duplicated with the previously created loader, and if it is not, the callback is where the onCreateLoader()
new loader is created, which is usually CursorLoader
, Of course, it can be other custom loader subclasses. Create the query CursorLoader
results that need to call the constructor method, where the parameters need to be used ContentProvider
, and the ContentProvider
following query parameters:
1、Uri:检索内容的Uri地址 2、projection:需要查询的列,若传入null则表示查询所有列,这样效率较低 3、selection:需要查询的行,若传入null则表示查询所有行 4、selectionArgs:需筛选的参数 5、sortOrder:排序规则
Example:
//If Non-null, the current filter of the user has provided.String Mcurfilter; PublicLoader<cursor>Oncreateloader(intID, Bundle args) {//This was called when a new Loader needs to be created. this //Sample only have one Loader, so we don ' t care about the ID. //First, pick the base URI to use depending on whether we is //Currently filtering.Uri BaseUri;if(Mcurfilter! =NULL) {BaseUri = Uri.withappendedpath (Contacts.content_filter_uri, Uri.encode (Mcurfilter)); }Else{BaseUri = Contacts.content_uri; }//Now Create and return a Cursorloader //Creating a Cursor for the data being displayed.StringSelect="(("+ Contacts.display_name +"Notnull) and ("+ Contacts.has_phone_number +"=1) and ("+ Contacts.display_name +"! =")) ";return NewCursorloader (Getactivity (), BaseUri, Contacts_summary_projection,Select,NULL, Contacts.display_name +"COLLATE localized ASC");}
onLoadFinished()
: When the loader instance that was previously created stops loading, the method is called back, and the time when the method is called by the system is: The loader instance will be loaded before the last data is released (this method was guaranteed to being called prior to the Release of the last data is supplied for this loader). At this point, you should be aware of all the old data, but you should not release the data manually because loader still holds the data at this time.
When the app no longer uses the data, loader releases it. For example, you should not call a method manually when you are using it, and when you CursorLoader
close()
CursorAdapter
hold a CursorLoader
reference to the returned cursor object, you should call the swapCursor()
method to ensure that the old cursor object is not closed.
Examples are as follows:
// This is the Adapter being used to display the list‘s data.SimpleCursorAdapter mAdapter;...publicvoid onLoadFinished(Loader<Cursor>data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) mAdapter.swapCursor(data);}
onLoaderReset()
: When a loader that was previously created is rebuilt, the method is recalled. At this point, the data is not available. When the method is called back, the data will be released so that you can remove the reference to that data (the information is about to being released so can remove your reference to it).
Examples are as follows:
// This is the Adapter being used to display the list‘s data.SimpleCursorAdapter mAdapter;...publicvoidonLoaderReset(Loader<Cursor> loader) { // This is called when the last Cursor provided to onLoadFinished() // above is about to be closed. We need to make sure we are no // longer using it. mAdapter.swapCursor(null);}
Example (Example)
Here is an example of using Cursorloader:
Public Static class cursorloaderlistfragment extends listfragmentimplements Onquerytextlistener, loadermanager. loadercallbacks<Cursor> { The Adapter being used to display the list ' s data.Simplecursoradapter Madapter;//If Non-null, the current filter of the user has provided.String Mcurfilter; @Override Public voidonactivitycreated (Bundle savedinstancestate) {Super. onactivitycreated (Savedinstancestate);//Give Some text to display if there is no data. In a real //Application This would come from a resource.Setemptytext ("No phone Numbers");//We have a menu item to show in action Bar.Sethasoptionsmenu (true);//Create An empty adapter we'll use to display the loaded data.Madapter =NewSimplecursoradapter (Getactivity (), Android. R.layout.simple_list_item_2,NULL,NewString[] {contacts.display_name, contacts.contact_status},New int[] {Android. R.id.text1, Android. R.ID.TEXT2},0); Setlistadapter (Madapter);//Prepare the loader. Either re-connect with an existing one, //or start a new one.Getloadermanager (). Initloader (0,NULL, This); } @Override Public voidOncreateoptionsmenu (Menu menu, Menuinflater inflater) {//Place a action bar item for searching.MenuItem item = menu.add ("Search"); Item.seticon (Android. R.drawable.ic_menu_search); Item.setshowasaction (Menuitem.show_as_action_if_room); Searchview SV =NewSearchview (Getactivity ()); Sv.setonquerytextlistener ( This); Item.setactionview (SV); } Public BooleanOnquerytextchange (String newtext) {//Called when the Action Bar search text has changed. Update //The search filter, and restart the loader to do a new query // with the This filter.Mcurfilter =! Textutils.isempty (NewText)? NewText:NULL; Getloadermanager (). Restartloader (0,NULL, This);return true; } @Override Public BooleanOnquerytextsubmit (String query) {//Don ' t care on this. return true; } @Override Public voidOnlistitemclick (ListView L, View V,intPositionLongID) {//Insert desired behavior here.LOG.I ("Fragmentcomplexlist","Item clicked:"+ ID); }//These is the Contacts rows that we'll retrieve. Static Finalstring[] Contacts_summary_projection =NewString[] {contacts._id, contacts.display_name, Contacts.contact_status, Contacts.contact_pres ENCE, contacts.photo_id, Contacts.lookup_key,}; PublicLoader<cursor> Oncreateloader (intID, Bundle args) {//This was called when a new Loader needs to be created. this //Sample only have one Loader, so we don ' t care about the ID. //First, pick the base URI to use depending on whether we is //Currently filtering.Uri BaseUri;if(Mcurfilter! =NULL) {BaseUri = Uri.withappendedpath (Contacts.content_filter_uri, Uri.encode (Mcurfilter)); }Else{BaseUri = Contacts.content_uri; }//Now Create and return a Cursorloader //Creating a Cursor for the data being displayed.String select ="(("+ Contacts.display_name +"Notnull) and ("+ Contacts.has_phone_number +"=1) and ("+ Contacts.display_name +"! =")) ";return NewCursorloader (Getactivity (), BaseUri, Contacts_summary_projection, select,NULL, Contacts.display_name +"COLLATE localized ASC"); } Public voidOnloadfinished (loader<cursor> Loader, Cursor data) {//Swap the new cursor in. (The framework would take care of closing the //Old cursor once we return.)Madapter.swapcursor (data); } Public voidOnloaderreset (loader<cursor> Loader) {//This was called when the last Cursor provided to onloadfinished () //above is on to being closed. We need to make sure we is no //longer using it.Madapter.swapcursor (NULL); }}
More examples (more Examples)
For more examples of loader programs, you can refer to these links below:
Loadercursor
Loaderthrottle
Android Official Docs app components (loaders)