Android application has few ways to invoke method asynchronously, Thread, AsyncTask, Looper/Handler works in the same process. Service can cross process boundary.
1. thread
The most basic way to call method in a work thread is creating a thread object, the below sample creating a new work thread to do some work, and then calling view.post method to update UI in the main thread.
2. AsyncTask
AsyncTask standardizes the logic to create a work thread and then update the ui with the result, the above thread sample can be implemented using AsyncTask as below
3. Handler/Looper
Android uses MessageQueue, Looper and Handler to handle messages. By default, new work thread just created does not have a Looper associate with it, the thread can call Looper.prepare to start the looper.
A thread can have only only one Looper which manages a single message queue by Handler to consume the messages. Multiple Handler can associate with a Looper to consume messages, Handlers are automatically added into the current thread's looper if looper is not specified when it is constructed. Messages are sent or post to message queue by calling handler's method and that message will be processed by that particular handler .
Message can be sent/post to message queues from multiple threads by calling Handler's method, and the only single Looper thread dispatches and consumes the message. So part of Handler's logic (send/post) is running in producer threads, and part of Handler's logic (process) is running in consumer's Loop thread.
Handler.handleMessage does not handle runnable, as dispatchMessage will direct run the runnable by itself. In addition, unlike runnable, the same message cannot be post/sent to different handler.
1. thread
The most basic way to call method in a work thread is creating a thread object, the below sample creating a new work thread to do some work, and then calling view.post method to update UI in the main thread.
new Thread(new Runnable() {
public void run() {
final String workThreadInfo = "Work thread: " + getThreadSignature();
txtOutput.post(new Runnable() {
public void run() {
String uiThreadInfo = "UI thread post: " + getThreadSignature();
txtOutput.append("\r\n" + workThreadInfo);
txtOutput.append("\r\n" + uiThreadInfo);
}
});
}
}).start();
2. AsyncTask
AsyncTask standardizes the logic to create a work thread and then update the ui with the result, the above thread sample can be implemented using AsyncTask as below
new AsyncTask<Void, Void, Void>() {
String workThreadInfo;
@Override
protected Void doInBackground(Void... voids) {
workThreadInfo = "Work thread: " + getThreadSignature();
return null;
}
@Override
protected void onPostExecute(final Void result) {
String uiThreadInfo = "UI thread post: " + getThreadSignature();
txtOutput.append("\r\n" + workThreadInfo);
txtOutput.append("\r\n" + uiThreadInfo);
}
}.execute();
3. Handler/Looper
Android uses MessageQueue, Looper and Handler to handle messages. By default, new work thread just created does not have a Looper associate with it, the thread can call Looper.prepare to start the looper.
A thread can have only only one Looper which manages a single message queue by Handler to consume the messages. Multiple Handler can associate with a Looper to consume messages, Handlers are automatically added into the current thread's looper if looper is not specified when it is constructed. Messages are sent or post to message queue by calling handler's method and that message will be processed by that particular handler .
Message can be sent/post to message queues from multiple threads by calling Handler's method, and the only single Looper thread dispatches and consumes the message. So part of Handler's logic (send/post) is running in producer threads, and part of Handler's logic (process) is running in consumer's Loop thread.
Handler.handleMessage does not handle runnable, as dispatchMessage will direct run the runnable by itself. In addition, unlike runnable, the same message cannot be post/sent to different handler.
LooperThread mLooperThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e(TAG, "onCreate: " + getThreadSignature() );
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLooperThread = new LooperThread();
mLooperThread.start();
}
class LooperThread extends Thread {
public Handler mHandler;
public Handler mHandler2;
public void run() {
Log.e(TAG, "Looper thread run: " + getThreadSignature() );
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) { //only msg will get here
Log.e(TAG, "handleMessage: " + msg.toString() );
doLongRunningOperation(msg);
}
@Override
public void dispatchMessage(Message msg) { //both runnable and msg will get here
Log.e(TAG, "dispatchMessage: " + msg.toString() );
super.dispatchMessage(msg);
}
};
mHandler2 = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e(TAG, "handleMessage: " + msg.toString() );
doLongRunningOperation(msg);
}
@Override
public void dispatchMessage(Message msg) {
Log.e(TAG, "dispatchMessage: " + msg.toString() );
super.dispatchMessage(msg);
}
};
Looper.loop();
}
private void doLongRunningOperation(Message msg) { Log.e(TAG, "doLongRunningOperation in handler: what " + Integer.toString(msg.what) ); Log.e(TAG, "doLongRunningOperation in handler: " + getThreadSignature() ); } }
public void onLooperHandlerClicked(View v) { Log.e(TAG, "onLooperHandlerClicked: " + getThreadSignature() ); // Message msg= mLooperThread.mHandler.obtainMessage(); Message msg = Message.obtain(); msg.what = 100; mLooperThread.mHandler.sendMessage(msg); Runnable task = new Runnable() { @Override public void run() { Log.e(TAG, "runnable called at: "+ getThreadSignature()); } }; Message msg2 = mLooperThread.mHandler.obtainMessage(); msg2.what = 200; mLooperThread.mHandler2.sendMessage(msg); mLooperThread.mHandler2.post(task); }
HandlerThread implements the above logic, and can be used by only implementing the handler logic.4. ServiceAndroid Service is another option to handle async method, the caller calls a service provider to perform a task.
IntentService is a derived class of generic Service, which performs a service request called with startService, and then stops itself automatically.
Generic service will keep the service live when startService is called by caller and the service will stay there until stopService is called by caller.
Service can also implement bind, so it can expose a complex interface for caller to invoke
No comments:
Post a Comment