========================[ Readings ]======================== https://developer.android.com/guide/components/processes-and-threads.html (especially #WorkerThreads and "Using AsyncTask") https://developer.android.com/reference/android/os/AsyncTask.html Code in examples/Handler and examples/KittyDownload =================[ Android Threading model ]================= In Android, all View-related events and actions such as button clicks, measuring and redrawing of Views, etc., are processed in one main event loop, fed by one queue where these events are queued. This event loop code lives in something called a Looper (see below for a link on Looper internals). The thread that de-queues these events and dispatches them, e.g., drawing things on the screen, or calling callbacks, is your main thread in your Activity. In other words, this is the thread that calls your onClick()s, onCreate(..)s, and other lifecycle and listener functions for views, activities, and fragments. It follows that no CPU-heavy work can be done in your callbacks, because it will interfere with responsiveness of your UI. You cannot handle a download, play music, compress/decompress files, turn incoming streams of bytes into images, call sleep(). Unlike Unix scheduling, these tasks will not be pre-empted to take care of other tasks; your UI will just freeze for the duration. Let's say you call sleep(..) in some onClick() callback for one of your views. This callback will be called from inside the main loop; all the other callbacks to be called on the same thread will need to wait until it returns. The reality is a bit more complex, but you get the id,ea: the main UI thread is not for anything other than callbacks and quick tasks, and your callbacks had better be quick, too. For everything else, you need to start new Threads. Java makes it simple enough: you need to create a new thread object, give its constructor a function to run, then call start() on that object. As Java functions were not "1st class" objects when this interface was designed, you cannot _just_ give a function; you need to create an object that has a method called run(), i.e., implements the interface Runnable. It need not have anything else, and normally doesn't have anything else. It is just a lambda function wrapped in an object, a bit awkwardly. In Kotlin, you just use a function. Android Studio actually shows you the Kotlin syntax as it "folds" your Java code for readability. NOTE: The function run() defined in a new Runnable() so constructed has lexical scope access to the variables of the enclosing class such as an Activity. It's called a _closure_ in Programming languages terminology. This is what makes these functions particularly useful: they will run in a separate thread, but will have references to your class members, too. ======[ Calling functions on the UI thread from other threads ]====== So you spin off a "worker" thread to do some work, and your UI thread runs unburdened while that work is being done. However, when the work is finished, you want to update some element of the UI, or maybe redraw the whole screen. Occasionally, you also want to update some progress bar while you are doing the work, to show how much of it remains. (An aside: Many websites show a spinner "progress bar" that is just an animated gif. Its spinning tells you nothing of whether some useful work like loading some resource or running some query is going in the background or not. In other words, its actual purpose is to lie to the user. Do not lie to the user. When I see such spinners, I leave the site and never come back; many savvy users I know do the same.) So you want to be able to post a quick callback to the main/UI thread from other threads, if only to update some info, e.g., advance a progress bar. You certainly want to do that at the end of your worker thread's execution, to report back to the UI that the work has been done. There are several ways to do that, from the most primitive, called "post(..)", to the more sophisticated like Handler and AsyncTask. As the basis of all of these is the ability to post a callback to the main thread. The Activity (which owns the main loop code) knows how to do that, and exposes the method runOnUiThread(Runnable) . You can also use any View v in the activity to call v.post(Runnable) v.postDelayed(Runnable, long) The function/closure run() contained in the Runnable object will be called on the UI thread. Note that this function is defined in the lexical context of the Activity, and thus can access references to its context ("this" of the activity, the pointer to the actual Activity object), and the Activity's members, some of which are hopefully Views---otherwise, calling these functions would not be possible (say, to call v.post(..), you need some view v in scope!). Note that you tend to end up with nesting Runnables: one for the code to run _now_ (on thread's start()) and another to run _later_, when it comes the time to actually call post(..). ======================[ post() ]====================== The Guide illustrates this thusly: class MainActivity extends Activity { private View mImageView = ... ; // accessible to functions defined in this lexical scope public void onClick(View v) { // some UI element's callback new Thread(new Runnable() { // run this NOW, on start(), in a new thread public void run() { // a potentially time consuming task final Bitmap bitmap = processBitMap("image.png"); // CPU-heavy, could delay UI callbacks mImageView.post(new Runnable() { public void run() { // run this later, after processBitMap returns mImageView.setImageBitmap(bitmap); // referencing outer scope, a.k.a. "closure" } }); } }).start(); // <--- start the outer Runnable } ... } runOnUiThread(..) would behave the same, except you'll need a reference to the Activity to call it. Using "this" inside a Runnable would give you that Runnable, so you'd want to save "this" of the Activity somewhere above and use that: class MainActivity extends Activity { private Activity this_act; // ... this_act = this; // say, in onCreate(..) ... this_act.runOnUiThread(..) // inside a Runnable given to post(..) ... } Read this on how post(..) is implemented: http://blog.xebia.com/android-looper-anatomy/ ======================[ Handler ]====================== The Handler class (see examples/Handler) is more sophisticated. It abstracts away the activities and views, and gives you the ability to post functions (well, Runnable objects wrapping functions you actually want to execute) to whatever thread that the Handler has been created on. That way you can pass work between several threads, not just the main UI thread and a worker. Basic use of Handler is not that harder than that of runOnUiThread(..) and View.post(..): you create a new Handler object on the UI thread (say, in onCreate(..), and then reference it in some Runnable passed to a new Thread. You can then call post(..) of that handler object, and it will go to the UI thread on this it lives. Handler h; public void onCreate(..){ ... h = new Handler(); .. } new Thread( new Runnable(){ public void run(){ // do some work or sleep h.post( new Runnable(){ public void run(){ // do this on the UI thread } }); } }).start(); // because who doesn't love many layers of nesting parentheses? See for more details: https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler ======================[ AsyncTask ]====================== Runnables inside Runnables inside Runnables get boring really fast. Although you can specify any crazy patterns of passing control between threads, usually you want to do something like (a) set up a task, (b) run a task on a new thread, (c) report the result back when ready, and (d) occasionally update the UI from the task before it's done, so that the user can see some work is going on (hence the whole idea of a progress bar that doesn't lie, but faithfully represents progress of a task). So AsyncTask abstracts away just that. It offers methods doInBackground(..) for (b) onPostExecute(..) for (c) onProgressUpdate(..) for (d) onPreExecute(..) for (a) In a lot of use cases, skipping (a) and (d) is fine; (b) and (c) is really what you want. Read https://developer.android.com/reference/android/os/AsyncTask.html for details, in particular "Usage", "The 4 steps", and "Threading rules". You define these four methods in the AsyncTask definition, i.e., normally, in your own class that extends it. You never call them directly. Repeat, you never call them directly. Instead, on the UI thread, you create an object for your class and call execute(..) on that object. The rest happens automatically, and on the right threads: onPreExecute(..) on the UI thread, doInBackground(..) on a specially and automatically created worker thread, onProgressUpdate(..) on the UI thread (and ti should be brief!), and, finally onPostExecute(..) also on the UI thread. So, if you never call onProgressUpdate(..), how do you report progress from inside doInBackground(..)? You call publishProgress(..), another special part of the interface. You are thus freed from the burden of explicitly creating threads and peppering your code with unsightly nested Runnables. Instead, you get an intuitive pipeline of methods. ======================[ AsyncTask and types ]====================== This simplification comes at a cost, and that cost has to do with the type system. Since you are setting a pipeline, you want to make sure that the type that one stage consumes is the one the previous stage produces. Specifically, you want the argument of onPostExecute(..) to be just the type that doInBackground(..) returns. You also want to make sure that onProgressUpdate(..) gets exactly the same type as publishProgress(..) gets for its argument. So when you extend AsyncTask to get your own class to .execute(..), you must specify these type parameters in a template. For example, private class DownloadImageTask extends AsyncTask { means that doInBackground(..) gets an array of URLs (so the API designers decided; in case you want to pass just one URL, you retrieve it inside the function as [0]th element of the array), and returns a Bitmap. Consequently, onPostExecute(..) gets a Bitmap: protected Bitmap doInBackground(URL... urls) { // do something with urls[0] publishProgress( some_int ); // do something with urls[1], ... } protected void onPostExecute(Bitmap result) { // set some ImageView to result } and progress reporting is done by passing Integers: protected void onProgressUpdate(Integer... progress) { // another API choice for array, why? someprogressbar.setProgress(progress[0]); } } See more in https://developer.android.com/reference/android/os/AsyncTask.html ======================[ Putting it all together ]====================== A typical example of this is downloading files. See examples/KittyDownload, derived from DiMarzio's textbook. Other textbooks have similar examples. Note that HTTP used in this example is an insecure protocol. HTTP should not be used with data that has any value to users or can help attackers if they managed to change it in transit, via the so-called "Man in the middle" attacks. HTTPS should be the default; we will switch to it in later labs. Basically, the best use of HTTP is to debug HTTPS connectivity :)