一、了解Android消息機制
Android消息機制是指通過 Message、Handler 和 Looper 三者相互配合,實現在子線程中發送消息、處理消息,從而實現異步執行任務的方案。其中,Message 負責攜帶消息的內容,Handler 負責處理消息,而 Looper 則是消息循環機制的核心。在此機制下,我們可以在主線程中往子線程中發送消息,也可以在子線程中向主線程發送消息,從而實現更加靈活的多線程編程。
二、學習Looper類的基本結構
public class Looper {
private static final Object sLock = new Object();
private static Looper sMainLooper = null;
final MessageQueue mQueue;
private final Thread mThread;
private boolean mRun;
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
public static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
try {
msg.target.dispatchMessage(msg);
} finally {
msg.recycleUnchecked();
}
}
}
public static void quit() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
synchronized (me.mQueue) {
me.mRun = false;
me.mQueue.notifyAll();
}
}
public static Looper myLooper() {
return sThreadLocal.get();
}
}
以上是 Looper 類的源碼,其中最重要的屬性是 MessageQueue,它通過鏈表的結構保存所有需要執行的消息。Looper 自身則主要是調用 MessageQueue 的 next 方法進行輪詢,然後將消息交給對應的 Handler 處理,最後將 Message 回收利用以節約資源。
三、了解Message的實現
public final class Message {
public int what;
public int arg1;
public int arg2;
public Object obj;
public long when;
public Handler target;
Message next;
public int sendingUid = -1;
public Bundle data;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
private boolean mRecycled;
public static final int FLAG_IN_USE = 1 << 0;
int flags;
private static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
private static boolean gCheckRecycleUnchecked = true;
private Message() {}
public static Message obtain(Handler h) {
Message m = get();
m.target = h;
return m;
}
private static Message get() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0;
m.sendingUid = -1;
sPoolSize--;
return m;
}
}
return new Message();
}
void recycleUnchecked() {
if (mRecycled) {
if (gCheckRecycleUnchecked) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
mRecycled = true;
clearForRecycle();
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
void clearForRecycle() {
flags = 0;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
when = 0;
target = null;
// Explicitly target data to its more specific implementation to ensure
// that it's correctly recycled after a transfer.
data = null;
}
}
以上代碼是 Message 類的實現代碼,它主要包括消息類型和消息內容,配合 Handler 來執行對應的操作。其中 mostPoolSize 規定了該類允許緩存的最大實例數量,可以看到它通過靜態 sPoolSync 鎖實現了資源的共享,以此達到了 Message 回收、利用和避免浪費的效果。
四、創建一個自定義Handler進行消息處理
public class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 根據不同的消息類型,執行對應的操作
switch (msg.what) {
case 1:
// 執行操作1
break;
case 2:
// 執行操作2
break;
default:
break;
}
}
}
通過繼承 Handler 類,我們可以在自定義的 handleMessage 方法中處理各種不同消息類型的執行操作。其中,msg.what 用於表示消息類型,可以根據不同的需求來自定義,比如用數字表示不同的操作,或者用 final 常量來表示特定的操作。
五、在子線程中使用 Looper
public class MyThread extends Thread {
@Override
public void run() {
Looper.prepare();
MyHandler handler = new MyHandler();
Looper.loop();
}
public void sendMessage(Message msg) {
if (handler != null) {
handler.sendMessage(msg);
}
}
}
以上代碼演示了如何在子線程中使用 Looper。通過調用 Looper 類的 prepare 方法和 loop 方法,我們可以開始一個消息循環。在此循環中,我們可以根據不同的需求,使用自定義的 Handler 來處理消息邏輯。而 sendMessage 方法則是用於在 MyThread 中發送消息所用。
六、在主線程中使用 Handler
public class MainActivity extends AppCompatActivity {
private MyThread myThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThread = new MyThread();
myThread.start();
findViewById(R.id.btn_send_message).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.what = 1;
myThread.sendMessage(msg);
}
});
}
}
可以看到,MainActivity 中的 onCreate 方法中創建了一個 MyThread 線程,並在點擊按鈕的回調中發送了一個攜帶了消息類型為1的消息,這樣就能夠在子線程中執行對應的邏輯操作了。
七、總結
本文以 Android 中消息機制的核心類 Looper、Message 和 Handler 為中心,詳細介紹了消息循環、消息獲取、消息分發過程,還有如何在子線程中創建 Looper、Handler,以及如何在主線程中發送消息觸發相應的處理操作。只有充分理解 Android 的消息機制,才能更好的進行多線程編程,提高應用程序的性能與良好交互體驗。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/285441.html
微信掃一掃
支付寶掃一掃