@Nullable
public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
IntentFilter filter);
在主activity线程中注册一个BroadcastReceiver,该广播接收者会被任意匹配intentfilter的Broadcast在主应用程序线程中唤醒
@Nullable
public abstract Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler);
给这个广播接收者添加权限,这样只有具有同样权限的广播才能触发这个广播接收者,同时该方法可以通过最后一个参数scheduler来修改接收者所在线程位置,如果scheduler不为null,则会识别handler所在线程位置去处理接收者接收到的消息;如果handler为null,则接收者将在主线程
3: new Handler();
该构造函数调用的是Handler(Callback callback, boolean async)方法,只不过第一个参数为null,第二个参数为false,表示
创建一个和当前线程绑定的handler,如果当前线程没有looper,则不会收发消息,并会抛出一个异常
4: new Handler(Looper looper, Callback callback);
该构造函数调用的是Handler(Looper looper, Callback callback, boolean async),只不过第三个参数为false,表示
使用参数中的looper,并使用callback来进行收发消息,样例代码如下
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return true;
}
}
};
mHandler = new Handler(looper, mHandlerCallback);
5:Handler(Callback callback, boolean async)
使用当前的线程的looper的callback去处理消息,async表示是同步处理还是异步处理消息
6:Handler(Looper looper, Callback callback, boolean async)
使用当前的Looper,并使用callback去处理消息,async表示是同步处理还是异步处理消息
关于Handler构造函数的总结:
在handler的构造函数中,均会调用其他构造方法;在最后的构造中,都会用到async这个值,async的值表示Handler处理消息的能力是同步的还是异步;在默认的Handler构造中,默认是同步处理消息的,即当handleMessage处理完一条消息之后,才会接着处理另外一条消息;
那这里的async为true的时候,表示handler是异步的是用在哪里尼
在我们通常的做法中,通过handler发消息来更新UI,我们也称之为异步处理消息,当此时的async的值是false,表示消息发送是同步的;当async的值为true的时候,主要使用场景如下:
为了让View能够有快速的布局和绘制,android中定义了一个Barrier的概念,当View在绘制和布局时会向Looper中添加了Barrier(监控器),这样后续的消息队列中的同步的消息将不会被执行,以免会影响到UI绘制,但是只有异步消息才能被执行。 所谓的异步消息也只是体现在这,添加了Barrier后,消息还可以继续被执行,不会被推迟运行。
解释如下:
当ViewRootImpl开始measure和layout ViewTree时,会向主线程的Handler添加Barrier
//scheduleTraversals()方法都会在requestLayout时会被调用
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
void unscheduleTraversals() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
mChoreographer.removeCallbacks(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}
问题一:
当一个activity正在绘制界面,此时通过handler来更新界面,这个操作能够成功吗?
如果不能成功,该如何操作;
这个操作不能成功,如果想成功,则构建一个异步的Handler即可
问题二:
如何避免在创建Handler的时候出现的内存泄漏
当handler类为内部类的时候,会持有对外部类的引用,
为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。
static class MyHandler extends Handler {
WeakReference<MyActivity> mActivity;
MyHandler(MyActivity activity) {
mActivity = new WeakReference<MyActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
}
};
当时使用弱引用,会出现空指针的情况,那最好的解决方式为:将handler抽取为外部单独的类,并对activity做判空处理
public class MyHandler extends Handler {
WeakReference<MyActivity> mActivity;
MyHandler(MyActivity activity) {
mActivity = new WeakReference<MyActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MyActivity activity = mActivity.get();
if(activity == null)
return;
}
};
那有没有更为简洁的方式尼,答案是有的
private Handler myHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
因为这种方式不存在匿名内部类,而非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用
问题三:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//do something
super.handleMessage(msg);
}
};
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//do something
return true;
}
});
为什么第一种是匿名内部类,而第二种不是匿名内部类
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法;在第一种实现中,直接new handler类,并实现handleMessage方法,因此是匿名内部类;而在第二种实现中,传递了一个参数,完成了Handler的构造函数,因此其不是匿名内部类