Monday, 17 October 2016

Android - Proper way to load data asynchronously from Content Providers


Whenever we have to access data from Content Providers, generally everyone tends to use ContentResolvers and query the appropriate content providers using its URI and get the results. This is how android shows examples of using the COntentResolver as well. However there is a general problem that I have observed across different development teams that people tend to copy android's examples or code from stackoverflow and in doing so, forget a very important thing - ContentResolver runs in the app's main thread! (also called as the UI thread). 
The UI thread is a bad place for lengthy operations like loading data. You never know how long data will take to load, especially if that data is sourced from a content provider or the network. Android 3.0 (Honeycomb) introduced the concept of Loaders and, in particular, the CursorLoader class that offloads the work of loading data on a thread, and keeps the data persistent during short term activity refresh events, such as an orientation change. 

Step 1: Using the Right Class Versions
Normally, we can get away with just using the default import statements of Android Studio. However, for loaders to work, we must ensure that we are using the correct versions of the classes. Here are the relevant import statements:
import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.SimpleCursorAdapter;

public class NotificationsListFragment extends ListFragment implements         LoaderManager.LoaderCallbacks<Cursor> { // ... existing code // LoaderManager.LoaderCallbacks<Cursor> methods:     @Override     public Loader<Cursor> onCreateLoader(int id, Bundle args) {         // TBD     }     @Override     public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {         // TBD     }     @Override     public void onLoaderReset(Loader<Cursor> loader) {         // TBD     } }

// NotificationsListFragment class member variables private static final int NOTIFICATIONS_LIST_LOADER = 0; private SimpleCursorAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     String[] uiBindFrom = { TutListDatabase.COL_TITLE };     int[] uiBindTo = { R.id.title };     getLoaderManager().initLoader(NOTIFICATIONS_LIST_LOADER, null, this);     adapter = new SimpleCursorAdapter(             getActivity().getApplicationContext(), R.layout.list_item,             null, uiBindFrom, uiBindTo,             CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);     setListAdapter(adapter); }

As you can see, we've made the three changes. The Cursor object and the resulting query() call have been removed. In it’s place, we call the initLoader() method of the LoaderManager class. Although this method returns the loader object, there is no need for us to keep it around. Instead, the LoaderManager takes care of the details for us. All loaders are uniquely identified so the system knows if one must be newly created or not. We use the NOTIFICATIONS_LIST_LOADER constant to identify the single loader now in use. Finally, we changed the adapter to a class member variable and no cursor is passed to it yet by using a null value.
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {     String[] projection = { NotificationsListDatabase.ID, NotificationsListDatabase.COL_TITLE };     CursorLoader cursorLoader = new CursorLoader(getActivity(),             NotificationsListProvider.CONTENT_URI, projection, null, null, null);     return cursorLoader; }
As you can see, it's fairly straightforward and really does look like the call to managedQuery(), but instead of a Cursor, we get a CursorLoader. And speaking of Cursors...
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {     adapter.swapCursor(cursor); }
The new swapCursor() method, introduced in API Level 11 and provided in the compatibility package, assigns the new Cursor but does not close the previous one. This allows the system to keep track of the Cursor and manage it for us, optimizing where appropriate.

@Override public void onLoaderReset(Loader<Cursor> loader) {     adapter.swapCursor(null); }
HINT: It can be achieved with a single functional line of code that will require a try-catch block.

Thursday, 13 October 2016

Android - Loopers and Handlers



Android has a nice and beautiful concept of Loopers and Handlers. If you happened to do work on different threads, chances are you run into Loopers and Handlers. So what are Loopers and Handlers? Basically, they implement a common concurrency pattern that I call the Pipeline Thread. Here’s how it works:
  • The Pipeline Thread holds a queue of tasks which are just some units of work that can be executed or processed.
  • Other threads can safely push new tasks into the Pipeline Thread’s queue at any time.
  • The Pipeline Thread processes the queued tasks one after another. If there are no tasks queued, it blocks until a task appears in the queue.
  • Sometimes tasks can called messages and other names.

Usages of the Pipeline Thread
  • Executing requests to a remote service (usually you want to do them one by one and sequentially)
  • Uploading images to an HTTP service
  • Resizing and processing images (I once developed a picture uploader :))
  • Downloading stuff, just like we’re going to do in our app

Looping and Handling?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void run() {
  try {
    // preparing a looper on current thread    
    // the current thread is being detected implicitly
    Looper.prepare();
    // now, the handler will automatically bind to the
    // Looper that is attached to the current thread
    // You don't need to specify the Looper explicitly
    handler = new Handler();
     
    // After the following line the thread will start
    // running the message loop and will not normally
    // exit the loop unless a problem happens or you
    // quit() the looper (see below)
    Looper.loop();
  } catch (Throwable t) {
    Log.e(TAG, "halted due to an error", t);
  }
}
After that, you can just pass the handler to any other thread. It has a thread-safe interface that includes many operations, but the most straightforward ones arepostMessage() and its relatives.?
1
2
3
4
5
6
handler.post(new Runnable() {
  @Override
  public void run() {      
    // this will be done in the Pipeline Thread      
  }
});
In our case, we will use this idiom to schedule download tasks to be performed (on the download pipeline thread) when the user clicks a button (which is handled on the UI thread). We will also use it the other way around – when the download thread notifies the activity that a download has completed (on the download thread), the activity will use a Handler that is attached to the UI thread to make sure that we update the UI on the UI thread only (which is a requirement of Android UI).?
1
2
3
4
5
6
7
8
9
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
     
    // Create the Handler. It will implicitly bind to the Looper
    // that is internally created for this thread (since it is the UI thread)
    handler = new Handler();
}

Implementation Details?
01
02
03
04
05
06
07
08
09
10
11
12
// note! this might be called from another thread
@Override
public void handleDownloadThreadUpdate() {
  // we want to modify the progress bar so we need to do it from the UI thread
  // how can we make sure the code runs in the UI thread? use the handler!
  handler.post(new Runnable() {
    @Override
    public void run() {
      // update the UI etc.
    }
  });
}
Note: In case of doubt, it’s also OK to call a handler from its own thread.
Conclusion
This architecture has some valuable traits and is widely used in frameworks and applications on different platforms.

Llet’s discuss the Pipeline Thread for some more time and see how Looper and Handler implement it.

The most prominent usage of Pipeline Thread is found within almost any UI framework, including Swing (remember the event-dispatching thread?), SWT, Adobe Flex and, of course, Android Activities. The Pipeline Thread pattern is used to process UI events (such as button clicks, mouse movement, orientation changes, screen redraw and so on). This allows you to change a button caption without having to worry that the user will click the button at the same moment.
On the other hand, this forces you to only do quick operations in the UI thread – any developer knows what happens if you try to download a file right there in a buttononClick handler. In our app we will overcome that by adding another Pipeline Thread and pushing long-lasting operations (in our case, the downloads) to it so that the UI thread can run free.
Other common usages of the Pipeline Thread pattern:
In general, using a Pipeline Thread rather than launching another thread for each background operation allows you to control the load and order (almost like law and order) of your background jobs. Also, you can have multiple Pipeline Threads and use them as a pool so you will have both the ability to execute multiple operations at once and keep the load under control.
In the following example, we only want to allow one download at a time and we want downloads to execute in the order they were scheduled. Exactly the case to use a Pipeline Thread.

Looper is a class that turns a thread into a Pipeline Thread and Handler gives you a mechanism to push tasks into it from any other threads.
The Looper is named so because it implements the loop – takes the next task, executes it, then takes the next one and so on. The Handler is called a handler because someone could not invent a better name.
Here’s what you should put into a Thread‘s run() method to turn it into a Pipeline Thread and to create a Handler so that other threads can assign tasks to it:


Note: The Handler interface has many more cool operations, especially related to message passing,

For example, imagine another thread has a reference to the handler that was created in our Pipeline Thread. Here’s how that other thread can schedule an operation to be executed in the Pipeline Thread:


By the way, the UI thread has a Looper created for it implicitly, so you can just create a Handler in activity’s onCreate() and it will work fine:


If you understood the idea of Looper and Handler, the rest is details. Basically, I created a DownloadTask class that emulates a download task of a random duration. I did not want to do actual downloads because I didn’t want to eat your data plans, but it’s straightforward to change this into real work. Then, the DownloadThreadhas an interface that allows to enqueue DownloadTask instances and also to request it to exit gracefully. There is also the DownloadThreadListener interface that allows the download thread to notify some other entity about status updates. In our case, that interface will be implemented by the DownloadQueueActivity because we want to reflect the download progress in the UI.
At this point, however, we need to use another Handler – the one that is attached to the UI thread. The DownloadThreadListener is notified by the DownloadThreadfrom the download thread itself, but the action we want to take (updating the progressbar and the textview) needs to be done from the UI thread. Therefore we use the UI handler like this:



Of course, you should read the code and the comments to understand things clearly.
Also, it’s better to do things like background downloads in a service.
Loopers and Handlers allow you to do cool things. However, they are related to concurrency which is often a slippery area.