设为首页 加入收藏

TOP

android 在非UI线程更新UI仍然成功原因深入剖析(二)
2017-10-13 10:36:50 】 浏览:4100
Tags:android 在非 线程 更新 仍然 成功 原因 深入 剖析
.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:883)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:4320)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.view.View.invalidate(View.java:10947)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.view.View.invalidate(View.java:10902)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.widget.TextView.checkForRelayout(TextView.java:6673)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.widget.TextView.setText(TextView.java:3860)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.widget.TextView.setText(TextView.java:3718)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at android.widget.TextView.setText(TextView.java:3693)   02-02 16:44:38.786: E/AndroidRuntime(17907):    at com.example.demo.MainActivity$LooperThread.run(MainActivity.java:78)  

意思就是说,只有创建View层次结构的线程才能修改View,我们在非UI主线程里面更新了View,所以会报错。

 

但是你还没说为什么第一种调用方法为什么不报错啊!!!

先别着急,先看一下上面的报错信息,里面有好多东西可以研究呢!

    我们先从下面开始看,首先是LooperThread.run()报错了,为什么报错呢,再往上,因为我们调用setText了,再往上就是TextView.checkForRelayout,然后上面是invalidate,我们修改了文字,肯定要invalidate啊,谁调用的呢?原来是ViewGroup.invalidateChild,往上找啊找,终于找到了罪魁祸首,ViewRootImpl.checkThread()报错了!

   ViewRootImpl是什么玩意?这个玩意可很强大,你现在就只需要知道它能做很多和界面有关的事情就ok了,其实我对这个类也是只了解一点点。。。

 

   checkThread()到底做了什么啊,就报错!ViewRootImpl是一个隐藏类,我们只能去看源码,源码如下

void checkThread() {  
       if (mThread != Thread.currentThread()) {  
           throw new CalledFromWrongThreadException(  
                   "Only the original thread that created a view hierarchy can touch its views.");  
       }  
   } 

  就是这个方法报错了!ViewRootImpl是依附在AttachInfo这个类上的,而AttachInfo是View得一个隐藏类,你在Eclipse里面是看不到的,需要直接看framework得源码。所以说,这里的Thread.currentThread()是UI主线程,就是这里判断是不是我们在非UI主线做了修改VIew的操作。

 

    那么问题又来了,为啥第一种方式,不会报错呢!!!

   ok,不要抓狂,咱们先回顾一下Activity的生命周期。靠!和Activity的生命周期怎么又扯上关系了?

   Activity在onCreate中进行界面的数据准备,onStart()之后,Activity的界面就对用户可见了,那么知道这些有什么用呢?当然有用!上面两种调用方式的差别就在调用的时机不同!一个是在onCreate中开启线程调用,一个是我们手动调用,暗示着,第二种方法是在onResume之后调用!

    这种调用时机的差别就决定了代码中setText的意义!

    第一种做法中,虽然是在子线程中setText,但是这时候View还没画出来呢,所以并不会调用之后的inva

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇android TranslateAnimation 顶部.. 下一篇普通广播接收者和有序广播接收者

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目