Android:Activity.OnCreate方法中子线程可以更新UI,睡眠后不能更新UI的原因

从源码找答案:
随便找一个UI控件的更新操作,例如TextView的 setText 操作然后追踪:

TextView 类中:

private void setText(CharSequence text, BufferType type,
                         boolean notifyBefore, int oldlen) {
        ...
        if (mLayout != null) {
            checkForRelayout();//调用
        }
        ...
    }
    
    /**
     * 检查全新的文本是否需要新的视图布局
     * 或者只是一个新的文本布局
     */
    private void checkForRelayout() {
    //无论如何都会执行下面两行代码
            ...
            requestLayout();//重新请求布局
            invalidate();//重绘
            ...
    }

最后,invalidate()调用的是View中的invalidate方法

View 类中:

public void invalidate() {// 1
        invalidate(true);
    }
    
    public void invalidate(boolean invalidateCache) {// 2
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }
    
    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
            boolean fullInvalidate) {// 3
            ...
            final ViewParent p = mParent;
            if (p != null && ai != null && l < r && t < b) {
                p.invalidateChild(this, damage);
            }
            //调用ViewParent 接口的 invalidateChild方法,该接口被ViewRootImpl实现,
            //并且最终会调用ViewRootImpl的 invalidateChild方法
            //直接去看ViewRootImpl的 invalidateChild方法
            ...
    }
    
    

记住这个 if 条件,条件中 ViewParent 被 ViewRootImpl 实现。并且做了一个判断它不为空程序才会进行下去,因为 mParent 在 Activity 的 onResume 方法中被赋值。所以在onCreate时它是空的。这就是为什么在onCreate 中子线程可以刷新UI的原因。

ViewRootImpl 类中:

    public void invalidateChild(View child, Rect dirty) { // 1
        invalidateChildInParent(null, dirty);
    }
    
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) { // 2
        checkThread();
        ...
    }
    
    void checkThread() { // 3 在这里 判断并抛出异常
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }
    

对,没错,最后的最后,就是在这里 判断并抛出异常的。因为在View中对 ViewParent 实现类有一个判断,当它不为空时才会执行到这里,而 ViewParent 在Activity生命周期的 OnResume 方法中才会被赋值。所以在 onCreate 方法中如果使用子线程是可以做一波更新UI操作的。线程在CPU中调度随机的关系,子线程到这个判断的时候,主线程可能并没有创建ViewParent并赋值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.unionmed.unionhealth/com.unionmed.activity.restructure.ui.activity.user.aa.AddUserActivity}: java.lang.NullPointerException: Gson().fromJson(json, object : TypeToken<List<UserListBean>>() {}.type) must not be null at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3895) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4074) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2473) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:219) at android.app.ActivityThread.main(ActivityThread.java:8347) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055) Caused by: java.lang.NullPointerException: Gson().fromJson(json, object : TypeToken<List<UserListBean>>() {}.type) must not be null at com.unionmed.activity.restructure.app.utils.CacheUtil.getUserList2(CacheUtil.kt:467) at com.unionmed.activity.restructure.ui.vm.AddUserViewModel.getUserList(AddUserViewModel.kt:27) at com.unionmed.activity.restructure.ui.activity.user.aa.AddUserActivity.initView(AddUserActivity.kt:34) at me.hgj.jetpackmvvm.base.activity.BaseVmActivity.init(BaseVmActivity.kt:47) at me.hgj.jetpackmvvm.base.activity.BaseVmActivity.onCreate(BaseVmActivity.kt:41) at me.hgj.jetpackmvvm.base.activity.BaseVmDbActivity.onCreate(BaseVmDbActivity.kt:20) at com.unionmed.activity.restructure.app.base.BaseActivity.onCreate(BaseActivity.kt:46) at android.app.Activity.performCreate(Activity.java:8085) at android.app.Activity.performCreate(Activity.java:8073) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3868) ... 11 more是什么错误
最新发布
07-11

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值