Detailed explanation of the use of LoaderManager (1) --- The world before Loader

Part 1 The World Before Loaders

This part will give a brief introduction to Loaders and LoaderManager. The first section will be how to load data before Android3.0, pointing out its defects. The second section describes the purpose of each class and their ability to load data asynchronously.
This article is the beginning of a series of articles about Loaders and LoaderManager, the series is as follows:

1: The world before Loaders
2 : Understanding LoaderManager
3: Implementing Loaders
4: Example: AppListLoader

If you don't know anything about Loaders and LoaderManager, before continuing reading , I strongly recommend that you read the Loaders wizard.

Previous situation
Before Android 3.0, many applications were deficient in responsiveness. Glitches between UI switches, activity switching delays, ANR issues. Most of the failures in responsiveness stem from the fact that most developers execute queries in the UI thread-loading data this way is the worst option.

While this article emphasizes timely feedback, APIs prior to Android 3.0 do not seem to support this feature. Before Loaders, cursors were mainly managed and queried through two Activity methods (now deprecated):

public void startManagingCursor(Cursor)
Tell the activity to manage the cursor's life cycle according to its own life cycle. The cursor is automatically deactivate() when the activity is stopped. Will automatically close() when the activity is destroyed. When the activity is restarted after being stopped, the cursor will re-queried (requery()) to re-query the latest data.

public Cursor managedQuery(Uri, String, String, String, String)
This function is a wrapper for the query() method of ContentResolver. In addition to executing the query, startManagingCursor(cursor) will be called before it returns. That is to say, the cursor of this query is put into the activity life cycle management.

While it is very convenient to use, the above method will cause serious delay problems when performing query operations in the UI thread. Moreover, the "managed cursors" method will not retain data when the activity configuration changes (configuration changed, horizontal and vertical screen switching, keyboard pop-up, etc.). In these cases, the data will be requry()ed, but it is actually unnecessary, inefficient, and can cause sluggish and stuttering direction switching.

The Managed Cursors Problem
Let 's simulate the managed cursors problem in a simple code. The code provided below is to load data in a ListActivity using APIs before Android 3.0. This activity queries data from the ContentProvider and manages the returned cursor. The query results are wrapped in SimpleCursorAdapter and displayed in the listview. The code is refined as follows:
public class SampleListActivity extends ListActivity {  
  
  private static final String[] PROJECTION = new String[] {"_id", "text_column"};  
  
  @Override  
  protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate (savedInstanceState);  
  
    // Performs a "managed query" to the ContentProvider. The Activity   
    // will handle closing and requerying the cursor.  
    //  
    // WARNING!! This query (and any subsequent re-queries) will be  
    // performed on the UI Thread!!  
    Cursor cursor = managedQuery(  
        CONTENT_URI,  // The Uri constant in your ContentProvider class  
        PROJECTION,   // The columns to return for each data row  
        null,         // No where clause  
        null,         // No where clause  
        null);        // No sort order  
  
    String[] dataColumns = { "text_column" };  
    int[] viewIDs = { R.id.text_view };  
   
    // Create the backing adapter for the ListView.  
    //  
    // WARNING!! While not readily obvious, using this constructor will   
    // tell the CursorAdapter to register a ContentObserver that will  
    // monitor the underlying data source. As part of the monitoring  
    // process, the ContentObserver will call requery() on the cursor   
    // each time the data is updated. Since Cursor#requery() is performed   
    // on the UI thread, this constructor should be avoided at all costs!  
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(  
        this,                // The Activity context  
        R.layout.list_item,  // Points to the XML for a list item  
        cursor,              // Cursor that contains the data to display  
        dataColumns,         // Bind the data in column "text_column"...  
        viewIDs);            // ...to the TextView with id "R.id.text_view"  
  
    // Sets the ListView's adapter to be the cursor adapter that was   
    // just created.  
    setListAdapter(adapter);  
  }  
}

There are 3 problems with the above code. If you have read the above, then the first two questions are not difficult to read.

1. managedQuery performed a query operation in the Ui thread, which will cause the application to become unresponsive, this method should not be used anymore.
2. By looking at the Activity.java source code, you can know that managedQuery also calls startManagingCursor to manage the queried data. It seems very simple, because we don't need to consider the subsequent closing, requery, etc. of the cursor. But using this method results in the need to re-query the data every time the activity's state returns from stopped, which usually causes the UI thread to freeze. Having an activity manage the cursor for us is more risky than convenience.
3. The SimpleCursorAdapter constructor on line 32 is obsolete and should no longer be used. The problem with this constructor is that it will cause the SimpleCursorAdapter to automatically query when there are changes. More specifically, CursorAdapter will register a ContentObserver listener on the data, and will requery the data when the monitored data changes. We should use the standard constructor (if you are trying to use CursorLoader to load adapter data, make sure the last parameter passed in is 0). If you can't understand the third, that's okay, it's just a small mistake.

The release of Android tablet devices should enhance UI friendliness (more responsive). Larger devices, 7- to 10-inch tablets have more complex applications, more interactions, and more interface layouts. Fragments will be introduced later. Fragments make applications more dynamic and event-driven. A simple, single-threaded approach to loading data is clearly no longer appropriate. So this is the background of the birth of Loader and LoaderManager in Android 3.0.

Android3.0, Loaders, LoaderManager
Before Honeycomb, it was difficult to manage the operations of cursors, for example, to synchronize properly in the UI thread, to ensure that all queries were executed in a timely manner in the background thread. Android3.0 introduced Loader and LoaderManager classes to simplify the process. These two classes can be implemented in systems above Android 1.6 by using ASL (Android Support Library).
The new Loader API is a huge improvement, a huge improvement in user experience. Loaders ensure that all cursor operations are asynchronous, thus eliminating the possibility of blocking in the UI thread. Moreover, when managed by LoaderManager, Loaders can also maintain the current cursor data in the activity instance, that is, do not need to re-query (for example, when the activity needs to be restarted due to the horizontal and vertical screen switching). As an added bonus, Loaders are smart enough to automatically detect updates and re-retrieval of the underlying data when the data changes.

Summary Android apps have gotten better
since Honeycomb's Loaders and its implementation library. It is very inappropriate to use startManagingCursor and managedQuery now, not only will your program slow down, but there is a potential possibility of program freezing. On the other hand, Loaders can significantly improve the user experience by offloading data to a separate background process.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327006967&siteId=291194637