Android multithreading and asynchronous processing issues discussed in detail

  • 2020-05-10 18:52:38
  • OfStack

1. Raise questions
1) why multithreading?
2) how to realize multithreading?
3) what is the core of multithreading mechanism?
4) how many ways are there to implement it?

2. Problem analysis
1) the essence of multithreading is asynchronous processing, and intuitive 1 point is not to make users feel "stuck".
eg: you click on a button to download a song, and then the button 1 is pressed, and the user experience is poor.

2) multi-threaded implementation method: implements Runnable or extends Thread

3) the core mechanism of multithreading is Handler

4) the following implementation methods are provided
- - - 1 � Handler
-- -- -- -- -- - 1
When creating an Handler, 1 must be associated with an instance of Looper. The default constructor, Handler(), is Looper associated with the current Thread.
eg:
We create an Handler in UI Thread, then we associate Looper of UI Thread!
This point can be seen from the source!
The simplified code is as follows:
 
public Handler() { 
mLooper = Looper.myLooper(); 
// Current thread Looper In the Activity When created, UI The thread has been created Looper object  
// in Handler The mechanisms of Looper It's the core, it's the core 1 It's in a loop MessageQueue , there are  
// To be processed Message will Message Send to the current Handler Instance to handle  

if (mLooper == null) { 
throw new RuntimeException( 
 " Can't create handler inside thread that has not called Looper.prepare() " ); 
} 
// As you can see from the above, 1 a Handler Instances must be associated 1 a Looper Object, otherwise error  

mQueue = mLooper.mQueue; 
//Handler the MessageQueue , it is FIFO ? No! I think it's chronological  
// !!!! Message with MessageQueue What's the relationship? You can study if you are interested 1 The source code!  

mCallback = null; 
} 

You can also specify Looper when creating an Handler. The Looper object can be either of the current thread or of another thread!
Handler only handles Message in MessageQueue in Looper that it is associated with, and Handler doesn't really care which thread Looper it is associated with!
eg:
We created an Handler instance in the UI thread, which is passed into the Looper of the Worker thread. At this point, we can still do business!
eg:
-- create worker thread
 
private static final class Worker implements Runnable 
{ 
private static final Object mLock = new Object() ; 
private Looper mLooper ; 

public Worker(String name) 
{ 
final Thread thread = new Thread(null,this,name) ; 
thread.setPriority(Thread.MIN_PRIORITY) ; 
thread.start() ; 

synchronized(mLock) 
{ 
while(mLooper == null) 
{ 
try 
{ 
mLock.wait() ; 
} 
catch (InterruptedException e) 
{ 
e.printStackTrace(); 
} 
} 
} 
} 

@Override 
public void run() { 
synchronized(mLock) 
{ 
// This method can only be executed 1 time ,1 a Thread Can only be associated 1 a Looper 
Looper.prepare() ; 
mLooper = Looper.myLooper() ; 
mLock.notifyAll() ; 
} 
Looper.loop() ; 
} 

public Looper getLooper() 
{ 
return mLooper ; 
} 

public void quit() 
{ 
mLooper.quit() ; 
} 
} 

We can create an Handler in the UI thread and pass in Worker's Looper
eg:
-- define your own Handler
 
private final class MyHandler extends Handler 
{ 
private long id ; 

public MyHandler(Looper looper) 
{ 
super(looper) ; 
} 

@Override 
public void handleMessage(Message msg) { 
switch(msg.what) 
{ 
case 100 : 
mTv.setText( ""  + id) ; 
break ; 
} 
} 
} 

-- create Handler in Activity
this.mWorker = new Worker(" workerThread ");
this.mMyHandler = new MyHandler(this.mWorker.getLooper()) ;

- create Message
final Message msg = this.mMyHandler.obtainMessage(100);
msg. put (" test ", "test");
msg.sendToTarget() ;

Note that each Message must have its own instance of Target or Handler!
The source code is as follows:
 
public final Message obtainMessage(int what) 
{ 
return Message.obtain(this, what); 
} 

public static Message obtain(Handler h, int what) { 
Message m = obtain(); 
m.target = h;// It can be seen that message Associated with the current Handler 
m.what = what; 
return m; 
} 

The above only made 1 point of the original reason!

We usually use Handler mainly to deal with the asynchronous interaction problem of multi-threading!
Since Android stipulates that only the UI thread can update the user interface and accept the user's button and touch events!
The UI thread must not be blocked, so the time-consuming operation must start a new thread to process!
So the question is, how do you get the latest data back to the user after the time-consuming operation is over? We are currently working on the Worker thread, so we cannot update UI.
So what do you do? You have to get the latest data to where the UI thread can handle it! Now it's time to send Handler! But what did Handler do? The brief description is as follows:
The UI thread where Activity is located associates Looper and MessageQueue when it is created, so we create our own Handler in the UI thread, then Handler belongs to the UI thread, so it can interact with the UI thread!
UI thread Looper1 is directly in Loop operation MessageQueue reads Message to its target Handler to process! So, all we have to do is put the latest data in the Worker thread into MessageQueue of Looper with which Handler is associated, whereas Looper1 operates directly in loop, and once there is a qualified Message, we hand Message to target of Message at the first time, Handler! So, when we create Message we should specify target which is Handler!
But we can also, new Message() -- > mHandler. sendMessage (msg); This is a special case!
If we get the Message object through the obtainMessage() method, Handler will automatically set target of Message. You can see the source!

A simple one is:
UI thread or Worker thread provides MessageQueue, Handler fills Message, Looper reads Message from Looper, and then Message's own target, Handler, handles it!! Finally, the handlMessag(Message msg) method of Handler that belongs to the UI thread is called!!

This is the core of Android multithreaded asynchronous processing!!
A little wordy!!

*******************************************************************
Create Handler in the UI thread [1 inheritance HandleMessage(Message msg)]

|
Looper can belong to either the UI thread or the Worker thread

|
MessgeQueue, Looper1 directly under loop(), msg.target.dispatchMessage (msg); Call handleMessage of Handler (Message msg)

|
Get Message in the Worker thread and pass MessageQueue through Handler
*******************************************************************

When an Looper is created, MessageQueue is created that is subordinate to the Looper
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}

- - 2 - � View
post(Runnable action)
postDelay(Runnable action , long miliseconds)

- 3 - � � Activity
runOnUiThread(Runnable action)
The implementation of this method is simple:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
// if the current thread is not an UI thread
mHandler.post(action);
} else {
action.run();
}
}
Among them:
mUiThread = Thread.currentThread() ;
mHandler = new Handler() 

- 4 - � � AsyncTask
Params,Progress,Result are all data types,
The type of data to be processed by Params
Type of processing schedule for Progress
The result returned after processing by Result

It's a simple way to do asynchronous processing!
Method execution order:
1)
The onPreExecute() wok is executed in the UI thread for some initialization

2)
doInBackground (Params... The wok is executed in the Worker thread for time-consuming background processing, where publishProgress(Progress progress) can be called for progress processing

3)
The onProgressUpdate(Progress progress) wok is executed in the UI thread for real-time progress processing

4) onPostExecute(Result result), which is executed in the UI thread, and in the doInBackground(Params... params) after return call

5)
The onCancelled() wok is executed in the UI thread and is executed after the AsyncTask instance calls the cancle(true) method for some cleanup

A few notes:
AsyncTask must be created in the UI thread,
asyncTask. execute (Params... params); Execute in the UI thread and only once
To call execute again (Params... params), you must recreate the AsyncTask object

The last three methods are essentially implemented using Handler!

Related articles: