handler中的消息类型有3种:
(1)?? ?普通消息(同步消息);
(2)?? ?消息屏障(同步屏障);
(3)?? ?异步消息;
?屏障消息就是为了确保异步消息的优先级,设置了屏障后,只能处理其后的异步消息,同步消息会被挡住,除非撤销屏障。
插入消息屏障
?消息屏障:
- 没有target,即没有handler,不能分发;
- 带时间戳,在队列中也是按照时间戳排序的;而且,只能影响的时间戳后面的消息;
- 消息队列是可以插入多个消息屏障的;
- 插入到消息队列中,是没有唤醒线程的;
- 插入的消息屏障会返回一个token,这个token就是这个屏障的序号;
- 这个postSyncBarrier是一私有函数,只能通过反射来调用;
撤销(删除)消息屏障
?添加屏障的时候没有唤醒线程,反而是删除屏障的时候唤醒了线程;
消息屏障的处理
?
相关问题
插入消息时,如果消息队列中有消息屏障会怎么样?
?
//第一个问题:不会
//第二个问题,不会;
//第三个问题,可能会,看屏障的时间到了没有;
//第二个问题,可能会,看屏障的时间到了没有;
android源码中使用的消息屏障
在线程绘制的时候;
代码示例
对于的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();
}
});
}
}
说明:在点击插入屏障后,此时,插入普通消息,是不会执行的,当删除消息屏障时,普通消息才会执行;
参考:
Android Handler 机制(四):屏障消息(同步屏障)
|