Efficient Android Threading

63
Efficient Android Threading Anders Göransson [email protected] www.jayway.com www.jayway.com/blog www.oredev.org

description

 

Transcript of Efficient Android Threading

Page 1: Efficient Android Threading

Efficient Android Threading

Anders Göransson

[email protected]

www.jayway.com

www.jayway.com/blog

www.oredev.org

Page 2: Efficient Android Threading

Agenda

Optimize UI thread execution

Threads on Android

Asynchronous Techniques

Page 3: Efficient Android Threading

Threads on Android

UI

AndroidApp

LinuxProcess

Native ThreadsJava Threads

BG BG BG

Page 4: Efficient Android Threading

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

AndroidApp

Threads on Android

Page 5: Efficient Android Threading

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

App A

App A

Foreground Thread Group

Background Thread Group

App BApp B

Threads on Android

> 90%

< 10%

Page 6: Efficient Android Threading

Android Scheduling

1. Foreground

2. Visible

3. Service

4. Background

Process level:

App A

App A

Foreground Thread Group

Background Thread Group

App BApp B

Threads on Android

> 90%

< 10%

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

Page 7: Efficient Android Threading

LifecyclesThreads on Android

Activity Service

BroadcastReceiver

ContentProvider

Android Components

Java Objects

BroadcastReceiver

Activity Service

ContentProvider

LinuxProcess

Threads

BGBG

BG

UI

Page 8: Efficient Android Threading

Process

ApplicationStart

ApplicationEnd

LinuxProcess

Native Thread LifecycleThreads on Android

UI

BG

Time

Page 9: Efficient Android Threading

Example: Activity Lifecycle

Time

ActivityComponent

onCreate() onDestroy() onCreate() onDestroy()

ActivityObject

new() GC

ActivityObject

new() GC

Threads on Android

Page 10: Efficient Android Threading

Example: Activity Lifecycle

Time

ActivityComponent

onCreate() onDestroy() onCreate() onDestroy()

ActivityObject

new()

ActivityObject

new()

Threads on Android

Start

BG

Reference

Page 11: Efficient Android Threading

Background Threads

• A thread is a GC root

• Implement cancellation policy for your background threads!

Threads on Android

Page 12: Efficient Android Threading

Use Cases

Get off the UI thread

early!

Do long running task

Get off the UI thread

early!

Report result or

update UI

Do long running task

UIThread

BGThread

UIThread

BGThread

Page 13: Efficient Android Threading

Goal

What technique shall I use for my background thread

execution?

Page 14: Efficient Android Threading

Asynchronous Techniques

• Thread• Executor• HandlerThread• AsyncTask• Service• IntentService• AsyncQueryHandler• Loader

Page 15: Efficient Android Threading

Thread

• Plain old Java Thread

Page 16: Efficient Android Threading

Creation and StartThread

Thread t = new MyThread();t.start();

External Class

new Thread(new Runnable() {public void run() {

// Do long task}

}).start();

Anonymous Inner Class

Implicit reference to outer class

Page 17: Efficient Android Threading

Pitfalls

• Non-retained threads

• Missing cancellation policy

• Starting over and over again

Thread

Page 18: Efficient Android Threading

Good Use Cases

• One-shot tasks

• Post messages to the UI thread at end.

Thread

Page 19: Efficient Android Threading

Thread

One shot tasks

Page 20: Efficient Android Threading

Executor

• Powerful task execution framework.public interface Executor {

public void execute(Runnable r);

}

Executor

ExecutorService

ThreadPoolExecutor

Page 21: Efficient Android Threading

ExecutorServiceExecutor

Task submission:

executorService.submit(MyTask);executorService.invokeAll(Collection<Tasks>);executorService.invokeAny(Collection<Tasks>);

Lifecycle management:

executorService.shutdown();executorService.shutdownNow();

Lifecycle observation:

executorService.isShutdown();executorService.isTerminated();executorService.awaitTermination();

RunningShutting

DownTerminated

shutdown()

Page 22: Efficient Android Threading

Task / Execution Environment

Executor

Task:Independent unit of work executed anywhere

Runnablerun()

Callablecall()

Execution Environment:Technique used to execute the task

Executorexecute(Runnable)

Future future = executorService.submit(Callable);

FutureisDone()

isCancelled()cancel()

Task manager/observer:

Page 23: Efficient Android Threading

Thread Pools

• Executor managing a pool of threads and a work queue.

• Reduces overhead of thread creation

Executor

Page 24: Efficient Android Threading

Thread PoolsExecutor

Fixed Thread Pool Executors.newFixedThreadPool(3)

Cached Thread Pool Executors.newCachedThreadPool()

Single Thread Pool Executors.newSingleThreadExecutor()

Custom Thread Pool new ThreadPoolExecutor(corePoolSize, maximumPoolSize, aliveTime, unit, workQueue)

Page 25: Efficient Android Threading

Pitfalls

• Lost thread safety when switching from sequential to concurrent execution

Executor

Page 26: Efficient Android Threading

Good Use Cases

• Execute tasks concurrently• Multiple Http requests• Concurrent image processing• Use cases gaining performance from

concurrent execution.

• Lifecycle management and observation of task execution.

• Maximum platform utilization

Executor

Page 27: Efficient Android Threading

Thread Executor

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

One shot tasks

Page 28: Efficient Android Threading

HandlerThread

• Inherits from Thread and encapsulates a Looper-object.

• Thread with a message queue and processing loop.

• Handles both Message and Runnable.

Running Deadt.quit()t = new HandlerThread().start();

Page 29: Efficient Android Threading

How it worksHandlerThread

HandlerThread

Create and Start

Add Process

Message Queue

1

23

t = new HandlerThread("BgThread");t.start();

1Handler h = new Handler(t.getLooper()) {

@Overridepublic void handleMessage(Message

msg) {//Process message

}};

2

h.sendEmptyMessage(42);3

Page 30: Efficient Android Threading

HandlerHandlerThread

Runnable/Message submission:

Lifecycle management:

Runnable/Message removal:

removeCallbacks(Runnable);removeMessages(Message)

post(Runnable);postDelayed(Runnable);postAtTime(Runnable)postAtFrontOfQueue(Runnable);sendMessage(Message);sendMessageDelayed(Message);sendMessageAtTime(Message);sendMessageAtFrontOfQueue(Message);

Page 31: Efficient Android Threading

Good Use Cases

• Keep a thread alive

• Sequential execution of messages• Avoid concurrent execution on multiple

button clicks• State machine• Detailed control of message processing.

HandlerThread

Page 32: Efficient Android Threading

Thread

One shot tasks

Executor

HandlerThread

Concurrent executionOne shot tasks

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

“newSingleThreadExecutor”-alikeExecute Message and RunnableBetter clean up

Page 33: Efficient Android Threading

AsyncTask

• Wraps Handler/Looper thread communication.

• Utilizes the Executor framework.• Callbacks for UI operations and

Background operation.

Page 34: Efficient Android Threading

onCancelled()4b

How it worksAsyncTask

UIThread

BGThread

new AsyncTask.execute()1

onPreExecute()2

3doInBackground()

onPostExecute()4a

AsyncTask.cancel()

+

Page 35: Efficient Android Threading

How it worksAsyncTask

public class MyAsyncTask extends AsyncTask<String, Void, Integer> {

@Overrideprotected void onPreExecute() {}

@Overrideprotected Integer doInBackground(String... params) {

return null;}

@Overrideprotected void onCancelled(Integer result) {}

@Overrideprotected void onPostExecute(Integer result) {}

}

public class MyActivity extends Activity {

public void onButtonClicked(View v) {new MyAsyncTask().execute("SomeInputString");

}}

Page 36: Efficient Android Threading

Pitfalls

• Application Global Behavior

• execute()

• Cancellation

• Creation and Start

AsyncTask

Page 37: Efficient Android Threading

Application Global BehaviorAsyncTask > Pitfalls

execute()

Queue Thread Pool

Activity

execute()Activity

execute()Service

execute()Receiver

execute()*

Page 38: Efficient Android Threading

execute()

Execution behavior has changed over time

AsyncTask > Pitfalls

execute()< Donut:

execute()< Honeycomb:

execute()

executeOnExecutor(Executor)

>= Honeycomb:

Page 39: Efficient Android Threading

execute()AsyncTask > Pitfalls

<uses-sdk android:targetSdkVersion="12" />

<uses-sdk android:targetSdkVersion="13" />

“So, if I call AsyncTask.execute on Honeycomb and later my tasks will run

sequentially, right?”

“Right?!?”

“Eh, it depends…”

Page 40: Efficient Android Threading

CancellationAsyncTask > Pitfalls

• Cancel AsyncTask when component finishes lifecycle.• Avoid UI updates on unavailable component.

• cancel(true) == cancel(false) + interrupt()

• Implement cancellation policy.

Page 41: Efficient Android Threading

Creation and StartAsyncTask > Pitfalls

• at = new AsyncTask()• The first creation decides callback thread

• onPostExecute()• onPublishProgress()• onCancelled()

• at.execute()• Callback thread of onPreExecute()

Page 42: Efficient Android Threading

Thread Executor

HandlerThread

“newSingleThreadExecutor”Execute Message and RunnableBetter clean up

One shot tasks

AsyncTask

Subsequent execution

AsyncTask<Void, Void, Void>AsyncTask.execute(Runnable)

Task control

One task with UI callback

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

Concurrent execution

Page 43: Efficient Android Threading

Service

• Background execution on the UI thread

• Decouple background threads with other lifecycles, typically the Activity lifecycle.

Page 44: Efficient Android Threading

Example: Lifecycle Decoupling

Time

ActivityComponent

onCreate() onDestroy() onCreate() onDestroy()

Service

ServiceComponent

onCreate() onDestroy()

BG

Page 45: Efficient Android Threading

Good Use Cases

• Tasks executed independently of user interaction.

• Tasks executing over several Activity lifecycles or configuration changes.

Service

Page 46: Efficient Android Threading

Pitfalls

• Hidden AsyncTask.execute() with serial execution.

Service

Page 47: Efficient Android Threading

Thread Executor

HandlerThread

One shot tasks

AsyncTask

Subsequent execution

AsyncTask<Void, Void, Void>AsyncTask.execute(Runnable)

One task with UI callback

Service

Activity lifecycle independent tasks

“newSingleThreadExecutor”Execute Message and RunnableBetter clean up

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

Concurrent execution

Task control

Page 48: Efficient Android Threading

IntentService

• Service with a worker thread.

• On demand intents.

public class MyIntentService extends IntentService {

@Overrideprotected void onHandleIntent(Intent intent) {}

}

Page 49: Efficient Android Threading

Lifecycle

Time

IntentService

IntentServiceComponent

onCreate() onDestroy()

Intent 1BG Intent 2 Intent 3 Intent n

stopSelf()

Page 50: Efficient Android Threading

Good Use Cases

• Serially executed tasks decoupled from other component lifecycles.

• Off-load UI thread from BroadcastReceiver.

• REST client (ResultReceiver as callback)

IntentService

Page 51: Efficient Android Threading

Thread Executor

HandlerThread

One shot tasks

AsyncTask

Subsequent execution

AsyncTask<Void, Void, Void>AsyncTask.execute(Runnable)

One task with UI callback

Service

Activity lifecycle independent tasks

IntentService

“On demand”

“Continuous”

“newSingleThreadExecutor”Execute Message and RunnableBetter clean up

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

Concurrent execution

Task control

Page 52: Efficient Android Threading

AsyncQueryHandler

• API Level 1• Asynchronous operations on a

ContentResolver• Query• Insert• Delete• Update

• Wraps a HandlerThread

Page 53: Efficient Android Threading

How it worksAsyncQueryHandler

UIThread

BGThread

new AsyncQueryHandler();1

startQuery();startInsert();startUpdate();startDelete();

2

onQueryComplete();onInsertComplete();onUpdateComplete();onDeleteComplete();

3

DB operations

Page 54: Efficient Android Threading

Cons

• No cursor management• No content observation• No data retention on configuration

changes• Background thread can’t be forced to quit

AsyncQueryHandler

Page 55: Efficient Android Threading

Thread Executor

HandlerThread

One shot tasks

AsyncTask

Subsequent execution

AsyncTask<Void, Void, Void>AsyncTask.execute(Runnable)

One task with UI callback

Service

Activity lifecycle independent tasks

IntentService

“On demand”

“Continuous”

AsyncQuery

Handler

Asynchronous CRUD

“newSingleThreadExecutor”Execute Message and RunnableBetter clean up

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

Task control

Concurrent execution

Page 56: Efficient Android Threading

Loader

• API added in Honeycomb• Available in compatibility package• Load data in a background thread• Observes data changes• Retained on configuration changes• Connected to the Activity and Fragment

lifecycles

Page 57: Efficient Android Threading

BasicsLoader

Data Source

Loader

1 Load data in BG 2 Observe data

3 Lifecycle management 4 Retained on configuration change

Page 58: Efficient Android Threading

Data SourcesLoader

Any Data Source

ContentProvider

CustomLoader

CursorLoader

Hard Easy

Page 59: Efficient Android Threading

How It WorksLoader

public class AndroidLoaderActivity extends ListActivity implements LoaderCallbacks<Cursor>{

SimpleCursorAdapter mAdapter;

public void onCreate(Bundle savedInstanceState) { getLoaderManager().initLoader(0, null, this); }

@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {

return new CursorLoader(..., CONTENT_URI, ...);}

@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor c) {

mAdapter.swapCursor(c);}

@Overridepublic void onLoaderReset(Loader<Cursor> arg0) {

mAdapter.swapCursor(null);}

}

Page 60: Efficient Android Threading

PitfallsLoader

• Data loading will stop when Activity/Fragment is destroyed• Http requests not finished

Page 61: Efficient Android Threading

Good Use CasesLoader

• Loading data from Content Providers.

Page 62: Efficient Android Threading

Thread Executor

HandlerThread

One shot tasks

AsyncTask

Subsequent execution

AsyncTask<Void, Void, Void>AsyncTask.execute(Runnable)

One task with UI callback

Service

Activity lifecycle independent tasks

IntentService

“On demand”

“Continuous”

AsyncQuery

Handler

Asynchronous CRUD

Loader

Load data from CPData observing

Full CRUD

“newSingleThreadExecutor”Execute Message and RunnableBetter clean up

Execution abstractionRepetitive tasksConcurrent executionSequential executionExecution managementTask management

Task control

Concurrent execution

CustomLoader

Page 63: Efficient Android Threading

Thank you for listening!

Questions?