编者:李国帅
qq:9611153 微信lgs9611153
2020/6/11
背景:
android用久了,慢慢觉得,EventBus和broadcast很相近,但EventBus可比广播好用多了。
有个问题,在onEvent(XXXEvent event)函数里,能不能直接更新界面View呢?
下面做了一个测试。
首先:
在线程中收到socket消息,然后发送一个订阅事件
EventBusUtils.sendEvent(new XXXEvent(type));
EventBusUtils类在本文后面。
情景1:
在activity中响应订阅事件,刷新列表,但是列表并没有被刷新,但是不能正常调用。
android开发中经常碰到这个问题,没有出现任何问题,但是不会被执行,我们可以在日志中看到错误,分清哪些是致命的,不可忽视的,哪些是次要的,误报的。
@Subscribe
public void onEvent(XXXEvent event) {
//Log.d(TAG, "XXXActivity onEvent(XXXEvent event)");
//adapter.initListView(contentBinding.rrvList, getContext());
adapter.onRefresh();
}
会出现
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
情景2:
可能是必须在ui线程才能刷新列表。
@Subscribe
public void onEvent(XXXEvent event) {
//Log.d(TAG, "XXXActivity onEvent(XXXEvent event)");
new Handler().postDelayed(() -> {
//如果需要等待服务器响应,马上刷新列表数据可能不是最新数据。需要等待一段时间再去刷新数据
//adapter.initListView(contentBinding.rrvList, getContext());
adapter.onRefresh();
}, 500);
}
}
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
由此可见new Handler()中是否可以更新ui呢?是可以的,但是需要在界面线程泵中执行。
需要修改为
@Subscribe
public void onEvent(XXXEvent event) {
//Log.d(TAG, "XXXActivity onEvent(XXXEvent event)");
new Handler().postDelayed(() -> {
Looper.prepare();
//adapter.initListView(contentBinding.rrvList, getContext());
adapter.onRefresh();
Looper.loop();
}, 500);
}
}
情景3:
如果不需要等待,使用runOnUiThread则更好
runOnUiThread(new Runnable() {
@Override
public void run() {
//adapter.initListView(contentBinding.rrvConsult, getContext());
adapter.onRefresh();
}
});
EventBusUtils类
public class EventBusUtils {
public static void register(Object context){
if (!EventBus.getDefault().isRegistered(context)) {
EventBus.getDefault().register(context);
}
}
public static void unregister(Object context){
if (EventBus.getDefault().isRegistered(context)) {
EventBus.getDefault().unregister(context);
}
}
public static void sendEvent(Object object){
EventBus.getDefault().post(object);
}
}