在Android的开发中,非UI线程不能操作UI线程中的控件,即UI是非线程安全的。

我在上一篇文章中这样说过:

它是非UI安全的,也就是说,不接受非UI线程的修改请求。当我们通过别的线程(非主线程或者说是非原始线程)来修改它的时候,
会抛出这个异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
CalledFromWrongThreadException 这个字面上都理解过来了,是说这个请求来自于错误的线程。
Only the original thread that created a view hierarchy can touch its views 只有最初创建视图层次结构的线程才可以接触到这些视图。

有些朋友可以不太明白这样的解释,今天我又写了一个这样的例子,让我们来看一下。

为了方便测试,在布局中我只有一个TextView,我通过非UI线程来修改它上面显示的值。

可能很多朋友都会正常完成修改TextView上面的值,所以对这个非UI线程来修改UI线程抱有怀疑和不解,因为我们明明是通过一个非UI的线程来修改成功的啊。

这里涉及到一个多线程的关系。我们知道,一个进程有了两条或两条以上的线程我们就可以叫它多线程了,它是多个线程可以同时工作,我来举个例子,


我到食堂里吃饭,师傅尽职地在窗口打菜,这就是两个线程,然后我点了一份TextView,里面装着Modify。最后我拿到这份TextView,回到座位上把它给吃了。

这个例子一切正常,所以什么异常都没有,然后第二天我又去了这个食堂。这天不知是我去得早了,还是这个师傅动作有些慢了。

我到食堂里吃饭,师傅一边XXX一边在炒菜,我惊呆了。然后他把炒好的TextView端上来,我抛出一个恶心反胃的异常,逃走了再也没有再来过这家食堂。


这两个例子,一个报错了一个没有,其实就在于我到食堂的时间,师傅是否已经做好了菜,就像上面的例子,UI线程和MyThead线程几乎是同时执行,

但后者的工作量太少了,更改了TextView上面的字就完成了,这里UI线程把这个UI展示出来,一切都很正常。但要是我们让MyThead在run的时候先睡眠几秒钟呢?

或者是弄一个按钮,点击按钮后MyThead才开始?这样都是在UI线程加载完成后才通过非UI线程对它进行修改的,一定会报错!

这就是多线程编程,有时候你运行若干次,结果正确,并不表明你的逻辑就是对的。我们一定要遵循代码的规范,保持清晰的思维。


再举一个规范的例子:

myThread是服务生,在UI线程(食堂)中有一个myHandler(厨师),我告诉服务生我点的菜,服务生就开始run,然后send一个Message给厨师myHandler,
myHandler收到消息开始做菜的动作,最后UI线程展示这道做好的菜。


PS:没看到那些工作间都写着吗,非工作人员禁止入内!!!



更多相关文章

  1. [Android] android的消息队列模型
  2. Android当中的线程使用
  3. Android中Service与Thread的区别
  4. Android开发实践:使用Service还是Thread
  5. 从源码角度一步步分析AsyncTask的用法与原理
  6. Android的UI主线程是ActivityThread吗?
  7. Android(安卓)Asynchronous Http Client 中文手册
  8. ( 经典 ) Android深入浅出之Binder机制
  9. android 模态与非模态对话框实现

随机推荐

  1. Android 中的各种控件
  2. android通话记录的查询与删除
  3. Android GridView的使用方法
  4. Android 5.X新特性详解
  5. Activity之间传递对象
  6. android通过USB的MTP模式下,禁止用户在根
  7. 我的Android之旅——UI界面六大布局之认
  8. android Can't create handler inside th
  9. Android中main.xml界面参数笔记
  10. android 2.3 wifi (二)