UI更新 CalledFromWrongThreadException

在写Activity的时候需要进行UI更新,遇到了一些问题,记录一下:

1、单线程 vs 多线程。

单线程的好处是逻辑简单,不需要考虑线程间通讯问题,坏处是在进行诸如下载、更新、读写的操作的时候会阻塞当前线程,造成假死现象,无论是用户体验还是测试监控都是十分糟糕的选择。因此在这里我把实际处理的过程用新的线程处理,只有在UI需要更新的时候再通知UI线程更新。多线程时候线程间通讯有几种实现机制,Android的多线程也有两种写法,一种是按照Java原先的风格写runnable,貌似实际上没有新开线程,另一种是利用handler消息队列的方式,实际上有新开线程。具体的知识百度一下。注意线程循环在线程开始的位置需要加一行代码

Looper.prepare();

目的是准备消息循环,即使你没有用到handler也没有用到Looper.loop()。否则会报错。

2、UI更新。

在选择了多线程之后,写了一个线程来处理数据,其中涉及到更新progressbar的操作,直接操作的话会报错(CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.),提示必须要在UI线程才能进行UI操作,这个是Android系统限制。可以有几种方式,例如利用1中线程间通讯的方法通知UI线程的handler更新UI,还有一种不那么规范但是非常方便的方法:

Activity.this.runOnUiThread(new Runnable() {
                            public void run() {
                                //do something
                            }
                        });

将要进行UI更新的代码抛给UI线程。在只需要少量地方集中处理UI的时候非常方便,缺点是如果很多地方要用,这个代码无法复用,就成了垃圾代码。

3、线程中断。

通常来说线程运行到最后就会自然结束,因此我们可以通过一定的方法人为让线程立即运行到最后。看了一下没有特别好的方法,主要有两种:interrupt和flag。需要线程中断的情况通常是不知道线程执行结束时间但要强行中断,或者线程本身是个死循环需要外部条件触发中断。我这次遇到的是后者,我想人为结束一个长循环的线程。interrupt的做法是每次运行都等待一个时间,有点像键盘中断在指令中的地位(指令结束后等待键盘中断),需要设定一个等待(sleep)时间。我这里是一个长循环,所以就用了设定flag的方式,线程运行时先初始化标志位paused,然后在循环的时候每一次循环开头都判断标志位(因为这个是长循环而不是死循环,不能用while(!paused)这样的方式),外部要求结束线程时就把标志位paused置true并跳出循环,等待线程自然结束。

需要注意的是,Thread.stop()这个方法是不起作用的。

UI更新 CalledFromWrongThreadException

时间: 2024-10-13 16:11:12

UI更新 CalledFromWrongThreadException的相关文章

Android开发之UI更新交互机制与实例解析

android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask异步类方法等 本文下面就这三种方法进行了演示和代码实现. a.Handler机制通过使用消息机制来实现 b.RunOnUiThread方法是通过运行UI线程来达到更新UI的目的 c.AsyncTask是异步类,通过异步更新来更新UI 效果图如下:           (1)Java功能实现代码如下:

WPF多线程UI更新——两种方法

WPF多线程UI更新--两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对象.)这是很常见的一个错误,一不小心就会有这个现象.在WPF中,如果不是用多线程的话,例如单线程应用程序,就是说代码一路过去都在GUI线程运行,可以随意更新任何东西,包括UI对象.但是使用多线程来更新UI就可能会出现以上所说问题,怎么解决?本文章提供两个方法:Dispatcher(大部分人使用),T

android开发之在activity中控制另一个activity的UI更新

转自:http://blog.csdn.net/jason0539/article/details/18075293 第一种方法: 遇到一个问题,需要在一个activity中控制另一个acitivity做一些更新,没想到传递handler的方法,通过以下方式解决. 1.在MyAPP中定义属性handler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package jason.com;     import jas

oc 多线程UI更新

1.在子线程中是不能进行UI 更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI.如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新 2.只有极少数的UI能,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如换标题,换背景图,但这没有任何意义

【Cocos2d-Js基础教学(7)界面UI更新方法(会用到第三方类库)】

我们游戏中会遇到很多UI更新的时候,大部分时候我们会remove该节点,再重新绘制的方法来进行UI更新. 但是这种更新效率并不高,这里我推荐大家一个第三方的库,来通过注册更新的方式来对UI进行更新管理: 它的大名其实很响亮,就是“js-signals”.官方地址:http://www.bootcdn.cn/js-signals/ 官方的定义是:Custom Event/Messaging system for JavaScript.(JavaScript自定义事件的消息传递系统.) 有兴趣的同学

Flutter 功能型组件:异步UI更新(FutureBuilder\StreamBuilder)

前言 很多时候会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面:又比如想展示Stream(比如文件流.互联网数据接收流)的进度.当然,通过StatefulWidget完全可以实现上述这些功能.但由于在实际开发中依赖异步数据更新UI的这种场景非常常见,因此Flutter专门提供了FutureBuilder和StreamBuilder两个组件来快速实现这种功能. 接口描述 FutureBuilder

android线程控制UI更新(Handler 、post()、postDelayed()、postAtTime)

按照下面的理解就是handler与ui线程有一定的关联可以因为更新界面只能在主线程中所有更新界面的地方可以在接受消息的handleMessage那里还有更新界面可以在handler.port(new Runnable))在自定义的线程中然后执行post方法通知主线程去更新这个界面 下面是参考: Android 线程是单线程的. 所以更新UI要用到Handler: private Handler splashHandler = new Handler() {public void handleMe

Android app主线程UI更新间歇性崩溃的问题

对App进行开发测试时,偶尔出现app崩溃的问题.日志如下: 10-25 18:44:52.935 15290-15290/com.zzq.cnblogs E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.zzq.cnblogs, PID: 15290 java.lang.IllegalStateException: The content of the adapter has changed but ListView did not re

关于android的UI更新机制与误区

Android系统的消息队列和消息循环都是主线程的,其它后台服务等无法直接更新,必须通过下面的消息队列,由主线程的消息循环去依次执行更新ui: 同时对于费时间超过5秒的事件,比如网络链接等,建议新开线程处理,否则系统会提示用户终止你. 扩招知识: Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列(Message Queue)和一个消息循环(Looper).Android中除了UI线程(主线程),创建的工作线程默认是没有消息循环和消息队列的