handler中的消息类型有3种:

(1)    普通消息(同步消息);

(2)    消息屏障(同步屏障);

(3)    异步消息;

Android handler 之消息屏障_异步消息

 屏障消息就是为了确保异步消息的优先级,设置了屏障后,只能处理其后的异步消息,同步消息会被挡住,除非撤销屏障。

插入消息屏障

Android handler 之消息屏障_异步消息_02

 消息屏障:

  1. 没有target,即没有handler,不能分发;
  2. 带时间戳,在队列中也是按照时间戳排序的;而且,只能影响的时间戳后面的消息;
  3. 消息队列是可以插入多个消息屏障的;
  4. 插入到消息队列中,是没有唤醒线程的;
  5. 插入的消息屏障会返回一个token,这个token就是这个屏障的序号;
  6. 这个postSyncBarrier是一私有函数,只能通过反射来调用;
撤销(删除)消息屏障

Android handler 之消息屏障_ide_03

 添加屏障的时候没有唤醒线程,反而是删除屏障的时候唤醒了线程;

消息屏障的处理

Android handler 之消息屏障_android_04

 Android handler 之消息屏障_java_05

相关问题

插入消息时,如果消息队列中有消息屏障会怎么样?

Android handler 之消息屏障_ide_06

 Android handler 之消息屏障_xml_07

//第一个问题:不会

//第二个问题,不会;

//第三个问题,可能会,看屏障的时间到了没有;

//第二个问题,可能会,看屏障的时间到了没有;

android源码中使用的消息屏障

在线程绘制的时候;

Android handler 之消息屏障_android_08

代码示例

对于的layout文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<Button
android:id="@+id/addBarrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Barrier"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent"/>

<Button
android:id="@+id/removeBarrier"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Remove Barrier"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<Button
android:id="@+id/normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send normal message"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<Button
android:id="@+id/async"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send async message"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</LinearLayout>

对应的activity文件:

package inuker.com.testbarrier;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Deque;
import java.util.LinkedList;

public class MainActivity extends Activity {

private HandlerThread mThread;
private Handler mHandler;

private Deque<Integer> mBarrierTokens = new LinkedList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mThread = new HandlerThread("");
mThread.start();

mHandler = new Handler(mThread.getLooper());

findViewById(R.id.addBarrier).setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
addBarrier();
}
});

findViewById(R.id.removeBarrier).setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
removeBarrier();
}
});

findViewById(R.id.normal).setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
sendNormalMessage();
}
});

findViewById(R.id.async).setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
sendAsyncMessage();
}
});
}

private void addBarrier() {
try {
Method method = MessageQueue.class.getMethod("postSyncBarrier");
method.setAccessible(true);
int barrierToken = (int) method.invoke(mHandler.getLooper().getQueue());
showToast(String.format("addBarrier success: %d", barrierToken));
mBarrierTokens.add(barrierToken);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

private void removeBarrier() {
if (mBarrierTokens.isEmpty()) {
return;
}
try {
Method method = MessageQueue.class.getMethod("removeSyncBarrier", int.class);
method.setAccessible(true);
int barrierToken = mBarrierTokens.pollLast();
method.invoke(mHandler.getLooper().getQueue(), barrierToken);
showToast(String.format("removeBarrier success: %d", barrierToken));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

private void sendNormalMessage() {
mHandler.post(new Runnable() {
@Override
public void run() {
// showToast("Normal Message");
Log.d("999","111 Normal");
}
});
}

private void sendAsyncMessage() {
Message msg = Message.obtain(mHandler, new Runnable() {
@Override
public void run() {
showToast("Async Message");
Log.d("999","222 Async Message");
}
});
msg.setAsynchronous(true);
msg.sendToTarget();
}

private void showToast(final String s) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
});
}
}

说明:在点击插入屏障后,此时,插入普通消息,是不会执行的,当删除消息屏障时,普通消息才会执行;​