Presentation is loading. Please wait.

Presentation is loading. Please wait.

Concurrency in Android

Similar presentations


Presentation on theme: "Concurrency in Android"— Presentation transcript:

1 Concurrency in Android

2 Process and Thread When a component of an app starts, the Android starts a process with a single thread in it. When another component needs to start, it is executed on the same thread in the same process. By default all components of the same app run in the same process.

3 Process lifecycle Five Level Importance Hierarchy
Foreground processes – most important Visible processes Service processes Background processes Empty processes – least important The system eliminates least important processes when memory is needed

4 Foreground Processes A process that is required for what the user is doing. One of the following conditions must be true: It hosts an activity that is in Resumed state It hosts a service that’s bound to the Resumed activity It hosts a service that is running in the foreground Service#startForeground() It hosts a service that is executing its lifecycle callbacks Such as onCreate(), onStart() It hosts a broadcastReceiver that’s running its onReceive() The system would not try to kill foreground processes only when the memory is too low for normal operations

5 Visible Processes A process that doesn’t have any foreground components, but still can affect what the user sees on screen. Either of the following must be true: It hosts an activity that is partially visible It hosts a Service that’s bound to a visible activity They will not be killed unless it is required to keep all the foreground processes running.

6 Service & Background & Empty
Service processes A process that is running a service that was started with startService() and it is not in Foreground and Visible groups. They would not be killed unless needed for foreground and visible processes to run Background processes A process hosts an activity that is not visible to the user (onStop() has been called) It has no direct impact on the user experience They may be killed any time in a Least Recently Used manner. Empty processes A process that doesn’t hold any active components. They are only kept for caching purposes They are the first to be killed for memory.

7 Threads Main Thread or UI Thread
when an app is launched, the system creates a thread, Main Thread, for the app. It is in charge of dispatching events to the user interface widgets. and It also interacts with UI components such as Views All components are instantiated in the UI thread System calls to each components are dispatched from this thread such as activity lifecylce callbacks. Thus called, Android Single Thread Model

8 ANR Exception ANR: Application Not Responding
Since the UI thread handles all events, long operations such as network access may block it from dispatching/handling events. If UI thread is blocked for a long period of time (5 secs), An ANR dialog will be shown to the user who may quit your app The Android UI toolkit is not thread-safe, so you must not access UI from other threads. Android.widget.* and android.view.* Simple Two Rules: Do not block the UI thread Do not access the UI toolkit from outside the UI thread

9 Worker/Background Threads
Java Threads Looper and Handler AsyncTask Loader AsyncTaskLoader CursorLoader

10 Looper and Handler A handler is a mechanism which
A Looper is a thread which Keeps a queue of tasks Executes the tasks one by one Other threads can insert tasks into the queue When the queue is empty, it waits A handler is a mechanism which Allows other threads to safely insert tasks into the queue A task is a object that implements Runnable

11 Examples The first example shows how to make a thread a looper and how to use another thread to post tasks to the looper Project: LooperAndHandler The second example shows how to post tasks to the UI thread in an Activity Project: LooperAndHandlerOnUiThread The third example shows how Messages may be posted from a thread to a looper and how to design a custom handler to process the Messages. Project: BasicThreadWithHandler

12 Looper Example 1 - 1 public class LooperThread extends Thread { private Handler public void run() { Log.i("LOOPER: ", "Looper started"); // initialize the current thread as a looper Looper.prepare(); // create a handler for the looper mHandler = new Handler(); // run the message queue in this thread Looper.loop(); } public Handler getHandler() { return mHandler;

13 Looper Example 1 - 2 public class TaskProducer extends Thread { private Handler mHandler; public TaskProducer(Handler handler) { this.mHandler = handler; } public void run() { Log.i("TaskProducer: ", "Started"); Runnable task1 = new Runnable() { Log.i("LOOPER: ", "Task 1 - started"); try { sleep(3000); } catch (InterruptedException e) {} Log.i("LOOPER: ", "Task 1 - Completed"); }; Runnable task2 = new Runnable() { Log.i("LOOPER: ", "Task 2 - started"); try { sleep(2000); } catch (InterruptedException e) {} Log.i("LOOPER: ", "Task 2 - completed"); mHandler.post(task1); mHandler.post(task2);

14 Looper Example 1 - 3 public class MainActivity extends Activity { private LooperThread protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // start the looper mLooper = new LooperThread(); mLooper.start(); } // start the task producer when a button is clicked public void startTaskProducer(View view) { TaskProducer taskProducer = new TaskProducer(mLooper.getHandler()); taskProducer.start(); ...

15 Looper Example 2 - 1 public class FileLoader extends Thread { private WeakReference<MainActivity> mWeakMainActivity; private String mFileName; private int mProgress; // why not to hold a progressbar here so we can set directly. public FileLoader(MainActivity activity, String fileName) { mWeakMainActivity = new WeakReference<MainActivity>(activity); mFileName = fileName; } public void run() { for (mProgress = 1; mProgress <= 10; mProgress++) { try { sleep(2000); } catch (InterruptedException e) {} // if there is a rotation and activity destroyed, force garbage collection System.gc(); // if the host activity is gone, do nothing, but return MainActivity strongRef = mWeakRefMainActivity.get(); if (strongRef == null) { Log.i("File Download", "Cancelled!"); return; // post progress update to UI thread strongRef.getHandler().post(new Runnable() // localStrongRef is necessary so the mainactivity is not // collected until we set localStrongRef to null. MainActivity localStrongRef = mWeakRefMainActivity.get(); if (localStrongRef == null) return; localStrongRef.getProgressBar().setProgress(mProgress * 10); localStrongRef.getTextView().setText("Downloading ... " + FileLoader.this.mFileName); localStrongRef = null; }); // since next post() could be a while, we don't want to retain the main activity during that strongRef = null;

16 Looper Example 2 - 1 // Continues from previous slide
// post "download complete" display MainActivity strongRef = mWeakRefMainActivity.get(); if (strongRef == null) { return; } strongRef.getHandler().post(new Runnable() { @Override public void run() { strongRef.getTextView().setText("Download - "+ FileLoader.this.mFileName + " complete"); strongRef = null; });

17 Looper Example 2 - 1 // the implementation has the potential for null pointer exception. Can you find the cause? public class FileLoader extends Thread { private WeakReference<MainActivity> mWeakMainActivity; private String mFileName; private int mProgress; public FileLoader(MainActivity activity, String fileName) { mWeakMainActivity = new WeakReference<MainActivity>(activity); mFileName = fileName; } public void run() { for (mProgress = 1; mProgress <= 10; mProgress++) { try { sleep(2000); } catch (InterruptedException e) {} // if the host activity is gone, do nothing, but return if (mWeakMainActivity.get() == null) return; // post progress update to UI thread mWeakMainActivity.get().getHandler().post(new Runnable() mWeakMainActivity.get().getProgressBar().setProgress(mProgress*10); mWeakMainActivity.get().getTextView().setText("Downloading ... " + FileLoader.this.mFileName); }); // post "download complete" display mWeakMainActivity.get().getTextView().setText("Download - "+ FileLoader.this.mFileName + " complete");

18 Looper Example 2 - 2 public class MainActivity extends Activity { private ProgressBar mProgressBar; private TextView mTextView; private Handler mHandler; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProgressBar = (ProgressBar)findViewById(R.id.progress_bar); mTextView = (TextView)findViewById(R.id.text_view); // create a handler for the implicit looper mHandler = new Handler(); } // called when a button is clicked. public void startBackgroundThread(View view) { FileLoader fileLoader = new FileLoader(this, "Dummy.txt"); fileLoader.start(); public ProgressBar getProgressBar() { return mProgressBar; public TextView getTextView() { return mTextView; public Handler getHandler() { return mHandler;

19 Looper Example 3 - 1 public class FileDownloadThread extends Thread { private WeakReference<Handler> mWeakRefHandler; private WeakReference<ProgressBar> mWeakRefProgressBar; private int mProgress; public FileDownloadThread(Handler handler, ProgressBar progressBar) { this.mWeakRefHandler = new WeakReference<Handler>(handler); this.mWeakRefProgressBar = new WeakReference<ProgressBar>(progressBar); } public void run() { for (mProgress = 1; mProgress <= 10; mProgress++) { // mimic downloading try { sleep(2000); } catch (InterruptedException e) {} Handler handler = mWeakRefHandler.get(); ProgressBar pBar = mWeakRefProgressBar.get(); if (handler == null || pBar == null) { // host activity is destroyed, so stop return; // post progress update to UI thread handler.post(new Runnable() if (pBar == null) { pBar.setProgress(mProgress*10); }); // send a message to UI thread Message message = Message.obtain(); message.what = 100; message.arg1 = mProgress; handler.sendMessage(message);

20 Looper Example 3 - 1 // this program has memory leak. It is for demo only. // DO NOT COPY and PASTE public class FileDownloadThread extends Thread { private Handler mHandler; // memory leak, do you see why? private ProgressBar mProgressBar; // memory leak, do you see why? private int mProgress; public FileDownloadThread(Handler handler, ProgressBar progressBar) { this.mHandler = handler; this.mProgressBar = progressBar; } public void run() { for (mProgress = 1; mProgress <= 10; mProgress++) { try { sleep(2000); } catch (InterruptedException e) {} // post progress update to UI thread mHandler.post(new Runnable() { @Override mProgressBar.setProgress(mProgress*10); }); // send a message to UI thread Message message = Message.obtain(); message.what = 100; message.arg1 = mProgress; mHandler.sendMessage(message);

21 Looper Example 3 - 2 public class MainActivity extends Activity { private ProgressBar mProgressBar; private TextView mTextView; private Handler protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mProgressBar = (ProgressBar)findViewById(R.id.progress_bar); mTextView = (TextView)findViewById(R.id.text_view); mHandler = new Handler() { public void handleMessage(Message message) { if (message.what == 100) { int percentage = message.arg1 *10; String text = "Downloading..."+percentage+"%"; mTextView.setText(text); toast(text); } }; // called when a button is clicked public void startBackgroundDownload(View view) { FileDownloadThread fileDownloader = new FileDownloadThread(mHandler, mProgressBar); fileDownloader.start(); private void toast(String text) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show();


Download ppt "Concurrency in Android"

Similar presentations


Ads by Google