使用SavedStateHandle时子线程更新数据UI未刷新问题咨询
问题根因
SavedStateHandle的set()方法内部会直接调用关联LiveData的setValue()方法更新数据,而setValue()要求必须在主线程调用,子线程调用会直接抛出CalledFromWrongThreadException异常。你在子线程中调用setUserId()触发mState.set(),异常被线程池默认的未捕获异常处理逻辑仅打印到Logcat、不会触发崩溃,因此你感知不到异常,数据更新实际未生效,自然不会触发UI刷新,可查看Logcat确认对应的线程异常日志。
你之前改用MutableLiveData时调用的postValue()方法本身做了线程适配,会自动将更新操作切换到主线程执行,所以可以正常触发UI回调。
解决方案
有两种常用修复方案:
方案1:修改setUserId方法,主动适配多线程调用
在setUserId中判断当前线程,子线程调用时自动切换到主线程再执行SavedStateHandle.set(),修改后代码如下:
public void setUserId(String value) { if (Looper.myLooper() == Looper.getMainLooper()) { // 主线程直接调用set mState.set(USER_KEY, value); } else { // 子线程切到主线程再更新 new Handler(Looper.getMainLooper()).post(() -> mState.set(USER_KEY, value)); } }
该方案侵入性最低,原有调用逻辑无需修改。
方案2:所有调用setUserId的位置主动切到主线程
比如子线程中更新数据时,先通过Activity.runOnUiThread或者View.post切换到主线程再调用setUserId:
// 以Fragment中子线程更新为例 Executors.newCachedThreadPool().submit(() -> { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } // 切主线程更新 requireActivity().runOnUiThread(() -> mViewModel.setUserId("111111")); });
内容的提问来源于stack exchange,提问作者Ethsaam Javaid
相关产品推荐
相关产品推荐

