編者:李國帥
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);
}
}