1. What are the ways of communication from child thread to main thread? The principle of sub thread to main thread communication?
This is a unique concept of Android. Communication mode between threads: eventbus, rxjava, livedata. However, the underlying principles of these methods are based on handler, so I will explain the principle of handler communication for you.
handler scheduling process:
Sub thread: handler.sendMessage(msg) = "handler.enqueueMessage =" MessageQueue.enqueueMessage())
Main thread: loop. Loop = "queue.next() =" handler.handleMessage())
Core schematic diagram of handler:
Illustrations of two important categories:
2. What is the cause of the handler memory leak?
JVM garbage collection mechanism: GCroot collection mechanism
Holding chain: static sThreadLocal -> mLooper ->MessageQueue ->msg ->handler -> activity
Solution: break the holding chain
3. How to create a handler in a child thread?
- Writing method 1: directly create a handler in the sub thread. Error
new Thread( () -> { Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { return false; } }); mHandler.sendMessage(new Message()); } ).start();
Error reporting display:
Process: com.wust.empty02, PID: 25002 java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-2,5,main] that has not called Looper.prepare() at android.os.Handler.<init>(Handler.java:207) at android.os.Handler.<init>(Handler.java:133) at com.wust.empty02.MainActivity.lambda$onCreate$0$MainActivity(MainActivity.java:20) at com.wust.empty02.MainActivity$$ExternalSyntheticLambda0.run(Unknown Source:2) at java.lang.Thread.run(Thread.java:919)
Error source location:
- Writing 2: correct writing
new Thread( () -> { //Create a looper for this thread Looper.prepare(); //Create a handler for this thread Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { return false; } }); //looper open loop Looper.loop(); } ).start();
This approach has a disadvantage: in this way, the thread can only create one handler.
- Writing 3: Pass public Handler(@NonNull Looper looper) use this constructor to create a handler
package com.wust.empty02; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyHandlerThread t = new MyHandlerThread(); t.start(); try { //If this sentence is removed, t.getmloop() will be null, because you can't guarantee that handler = new handler (t.getmloop()); Execute after t thread run Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } Handler handler = new Handler(t.getmLooper()); } } class MyHandlerThread extends Thread { private Looper mLooper; @Override public void run() { Looper.prepare(); this.mLooper = Looper.myLooper(); Looper.loop(); } public Looper getmLooper() { return mLooper; } }
From the comments of the above code, we can clearly see its shortcomings. No guarantee t. Getmloop () executes after the thread run method.
- Method 4: use HandlerThread create thread
HandlerThread t = new HandlerThread("wustyq"); t.start(); Handler handler = new Handler(t.getLooper());
This of the system Why can the run method in HandlerThread ensure that t. Before getlooper()?? Key codes + key ideas are as follows:
Why synchronized ? To solve the problem of concurrent operations = ", i.e. run and getLooper can only execute one at a time.
Why notifyAll() ? Because it is possible that multiple threads have called the wait() method to wait.
Why use while? No if? Because this wait() may be awakened by another thread, notify(). So use while to detect repeatedly.
4. What is the processing scheme for the Looper maintained in the sub thread when there is no message in the message queue? What's the usage? What about the main thread?
quit: loop exit. Prevent memory leaks. Will not be stopped.
5. How does the handler handle sending delayed messages?
The underlying Linux = "epoll" will be called to complete the wait
6. How should we create Message when we use it?
obtain()