In Android, the main thread (UI) cannot perform time-consuming operations, so the time-consuming operations need to be executed in the child thread, but the main thread needs to update the UI according to the execution of the child thread, so it involves the execution of asynchronous tasks.
In Android, asynchronous tasks can be executed in the following four ways: Handler, AsyncTask, HandlerThread, IntentService.
The use of these four asynchronous modes is described below.
A Handler.
Interthread communication.
MessageQueue: Message queue, responsible for storing messages Handler: responsible for sending and processing messages (sent and processed on different threads) Looper: An infinite loop to retrieve messages and notify Handler to process themCopy the code
The Handler saves the sent messages to the Message queue MessageQueue, and Looper constantly takes out the messages in the Message queue and gives them to the Handler for processing.
Use code:
Handler handler; . handler = new Handler(){ public void handleMessage(Message msg){ Log.d(TAG,"currentThread:"+ thread.currentThread ().getName()+" HandlerThread, received: MSG ="+ MSG); }}; new Thread(){ @Override public void run() { try { Thread.sleep(3000); Message message = new Message(); Message.obj = "I am Handler"; handler.sendMessage(message); } catch (InterruptedException e) { e.printStackTrace(); } } }.start();Copy the code
2. AsyncTask
A lightweight asynchronous task class that encapsulates the thread pool and Handler. By inheriting it directly, you can easily update the UI for the execution of asynchronous tasks in the background and the callback of the progress. Use code:
public class MyAsyncTask extends AsyncTask<String, Integer, Long> { public static final String TAG = "MyAsyncTask"; @Override protected Long doInBackground(String... params) { int count = 100; long total = 0; for(int i = 0; i < count; I++) {try{thread.sleep (1000); }catch (InterruptedException e) { e.printStackTrace(); } onProgressUpdate publishProgress((int) ((I/(float) count) * 100)); total ++; Log.d(TAG,""+((i / (float) count) * 100)); If (isCancelled()) {log.d (TAG,"AsyncTask isCancelled!!" ); break; } // Return the result to onPostExecute return total; }}Copy the code
Start AsyncTask task code:
HandlerThread myHandlerThread; . mMyAsyncTask = new MyAsyncTask(); // Start the task. Mmyasynctask.execute ();Copy the code
Terminate the AsyncTask task:
// Stop the task if (mMyAsyncTask! = null) { mMyAsyncTask.cancel(true); }Copy the code
Log information after the execution:
-------------mMyAsyncTask.execute()-------------- ...... 2021-08-07 18:46:13.910 9129-9679/ D/MyAsyncTask: 17.0 2021-08-07 18:46:14.9129-9679 / D/MyAsyncTask: 18.0 2021-08-07 18:46:15.941 9129-9679/ D/MyAsyncTask: 19.0 2021-08-07 18:46:16.900 9129-9679/ D/MyAsyncTask: 18.0 2021-08-07 18:46:16.900 9129-9679/ D/MyAsyncTask: 20.0 -- -- -- -- -- -- -- -- -- - mMyAsyncTask. Cancel (true); ------------ 2021-08-07 18:46:16.900 9129-9679/ D/MyAsyncTask: AsyncTask task cancel!!Copy the code
Analyze log information. Log operations correspond to operations one by one. Note that after mmyAsyncTask-cancel (true), doInBackground method isCancelled()=true in AsyncTask, thus break out of the task loop.
Three HandlerThread.
Inheriting Thread, which is essentially a Thread with a message loop, it builds Looper internally.
Use code:
myHandlerThread = new HandlerThread("handler_thread") ; myHandlerThread.start(); / / to the Handler specifies which myHandlerThread Handler = new Handler (myHandlerThread. GetLooper ()) {@ Override public void handleMessage(Message msg) { super.handleMessage(msg); // Receive the message from Handler, Log.d(TAG,"currentThread:"+ thread.currentThread ().getName()+" HandlerThread, received: MSG ="+ MSG); }}; New Thread(new Runnable() {@override public void run() {try {thread.sleep (3000); Message message = new Message(); Message.obj = "I am HandlerThread"; handler.sendMessage(message) ; } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); If (myHandlerThread! =null) { myHandlerThread.quit(); }Copy the code
Log information after the execution:
MainActivity: CurrentThread :handler_thread HandlerThread: MSG = {the when = 1 what ms = 0 obj = I am HandlerThread target = com. Example, myfirstproject. Async. MainActivity $6}Copy the code
Handler = new Handler() without arguments, because the main thread (UI) has looper.prepare () in the framework source. The Handler Handler handles the message code in the Main thread.
Look at the HandlerThread handler = new handler (myHandlerThread. GetLooper ()), is using a HandlerThread ThreadLooper name is “handler_thread”, The handleMessage is in the name of handler_thread.
Four IntentService.
A special type of Service, which inherits from Service and is an abstract class, is encapsulated to make it easier to perform background tasks, and internally uses HandlerThread to perform tasks. IntentService exits onDestory automatically when the task is completed.
Use code:
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; // /** // * Creates an IntentService. Invoked by your subclass's constructor. // * // * @param name Used to name the worker thread, important only for debugging. // */ // public MyIntentService(String name) { // super(name); // } public MyIntentService() { super(""); } @Override protected void onHandleIntent(Intent intent) { String action = intent.getStringExtra("action"); try { Thread.sleep(2000); } catch(InterruptedException e) { e.printStackTrace(); } log.d (TAG, "onHandleIntent is called, action:" + action); } @override public void onDestroy() {log.d (TAG, "onDestroy is called "); super.onDestroy(); }}Copy the code
Note that the correct constructor name for MyIntentService is public MyIntentService() with no arguments, not the IDE generated constructor public MyIntentService(String name). Otherwise the App will crash and throw an exception.
IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService IntentService
<service android:name=".xxx.MyIntentService" />
Copy the code
IntentService IntentService IntentService IntentService IntentService IntentService
Intent intent = new Intent(MainActivity.this, MyIntentService.class);
intent.putExtra("action","action_IntentService_1");
startService(intent);
intent.putExtra("action","action_IntentService_2");
startService(intent);
intent.putExtra("action","action_IntentService_3");
startService(intent);
Copy the code
Log information after the execution:
18:56:11. 820, 10804-10988 / D/MyIntentService: Action :action_IntentService_1 18:56:13.825 10804-10988/ D/MyIntentService: Action :action_IntentService_2 18:56:15.827 10804-10988/ D/MyIntentService: OnHandleIntent is called, action:action_IntentService_3 18:56:15.832 10804-10804/ D/MyIntentService: onDestroy is calledCopy the code
IntentService calls onDestroy after IntentService completes its task.
IntentService exits onDestory when the task is finished.
End!!