一,问题引入
异常: Only the original thread that created a view hierarchy can touch its views的解决方案
<wbr><wbr><wbr><wbr>为什么会有这种异常产生呢?</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>当每个应用程序apk第一次启动时,Android会同时启动一个对应的<span style="color:#ff0000; line-height:21px; word-wrap:normal; word-break:normal">主线程(Main Thread)</span>,</wbr></wbr></wbr>
<wbr><wbr><wbr>主线程负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,</wbr></wbr></wbr>
<wbr><wbr><wbr>并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做<span style="color:#ff0000; line-height:21px; word-wrap:normal; word-break:normal">UI线程</span>。</wbr></wbr></wbr>
<wbr><wbr><wbr>但是在开发Android应用时必须遵守单线程模型的原则:<wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><span style="color:#ff0000; line-height:21px; word-wrap:normal; word-break:normal">Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,如果在非UI线程中直接操作UI线程,</span></wbr></wbr></wbr>
<wbr><wbr><wbr>会抛出android.view.ViewRoot$CalledFromWrongThreadExc<wbr>eption: Only the original thread that<wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>created a view hierarchy can touch its views,这与普通的java程序不同。</wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒<span style="color:#ff0000; line-height:21px; word-wrap:normal; word-break:normal">用户终止应用程序(ANP)</span>。</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>因此android采用一种的Message Queue机制保证<span style="color:#ff0000; line-height:21px; word-wrap:normal; word-break:normal">线程间通信</span>。</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>Message Queue是一个消息队列,用来存放通过Handler发送的消息。</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr>Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,</wbr></wbr></wbr>
<wbr><wbr><wbr>activities,broadcast receivers 等,你可以在自己的子线程中创建Handler与UI thread通讯。</wbr></wbr></wbr>
<wbr><wbr><wbr>Handler会向message queue通过两种方法发送消息:send或post。</wbr></wbr></wbr>
<wbr><wbr><wbr>这两种消息都会插在message queue队尾并按先进先出执行,</wbr></wbr></wbr>
<wbr><wbr><wbr>但通过这两种方法发送的消息执行的方式略有不同:</wbr></wbr></wbr>
<wbr><wbr><wbr>1)通过send发送的是一个message对象,<wbr>会被handler的 handleMessage()函数处理;</wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>2)而通过post方法发送的是一个runnable对象,则会自己执行。</wbr></wbr></wbr>
<wbr><wbr><wbr>每个带图形界面的应用启动后,都会创建一个主线程,可称之为UI线程。</wbr></wbr></wbr>
<wbr><wbr><wbr>这个线程自动就会创建一个message queue,来自于系统的消息都会投放到这个message queue里面,</wbr></wbr></wbr>
<wbr><wbr><wbr>并按先进先出的顺序处理。</wbr></wbr></wbr>
<wbr><wbr><wbr>UI线程图形界面中的view可通过post方法向GUI线程的message queue投递一个runnable。</wbr></wbr></wbr>
<wbr><wbr><wbr>对于除UI线程以外的其他线程,创建时缺省并没有message queue,</wbr></wbr></wbr>
<wbr><wbr><wbr>而对于UI线程,则可以直接(比如在onCreate)创建一个handler并重载handleMessage,</wbr></wbr></wbr>
<wbr><wbr><wbr>省去创建message queue的过程。</wbr></wbr></wbr>
二,解决方案一
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 0)//成功
{
Log.d(TAG, "**********************start****************************");
playVideo(strVideoPath);//包含更新界面的方法
Log.d(TAG, "***********************end*****************************");
}
}
};
new Thread()
{
@Override
public void run()
{
// handler.post(runnableUi);
try{
Log.d(TAG, "######################start###############################");
handler.sendEmptyMessage(0);//UI线程外想更新UI线程
Log.d(TAG, "######################end###############################");
}
catch(Exception e)
{
Log.d(TAG, "***************************"+e.toString());
}
}
}.start();
三,解决方案二
Runnable runnableUi=new Runnable(){
@Override
public void run() {
//更新界面
textView.setText("the Content is:"+content);
}
};
new Thread(){
public void run(){
content=df.downLoadFiles();
handler.post(runnableUi);
}
}.start();
四,特别注意,引入函数包得时候,不要引入错误的包
import android.os.Handler; //这是正确的包
import java.util.logging.Handler;//不是这个包,而是上一个
分享到:
相关推荐
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 Android程序中可以使用的界面...
Android系统下,总结4种线程中操作UI界面的方法
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 Android程序中可以使用的界面刷新...
重点讲解为什么普通view不能在非UI线程刷新界面,而SurfaceView可以.内容为代码的demo而并非文档
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 Android界面刷新方法有两种,分别...
是一个工具包用来帮助设计和开发 Android 用户界面,包含三个单独的工具:Android Asset Studio用户界面原型模具,Android 设计预览,时常需要重复确认程序版面设计状况的 Android App 开发者,应该会爱上这个轻量级...
本文实例讲述了Android使用Sensor感应器实现线程中刷新UI创建android测力计的功能。分享给大家供大家参考,具体如下: 前面一篇《Android基于Sensor感应器获取重力感应加速度的方法》我们介绍了sensor的基本知识以及...
Demo-实例讲解线程池里面的UI如何刷新,处理两个开发者头疼的问题: 1. 数据经常需要读取更新,并且比较耗时,需要分步刷新UI....2. UI界面切换后,如何停止掉子线程里面正在读取的数据而不会将旧数据刷新到新UI界面上.
方法一:Activity.runOnUiThread(Runnable )(经验之道: 这个最好用, 凡是要刷新页面的地方,Activity.runOnUiThread( new Runnable() { public void run(){更新UI}});方法二:子线程调用Handler的sendMessage...
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。Android程序中可以使用的界面刷新...
在做界面开发时,无论是移动端的Android,还是我们这里讲的PyQt5,经常会有一个界面开发准则,那就是UI主线程与耗时子线程一定要分开,主线程负责刷新界面,耗时操作,如网络交互、磁盘IO等,都应该放在子线程里执行...
能学到什么:①UI界面绘制、减少层级嵌套、提升UI渲染性能和多线程怎么在android中体现的;②android分享功能、邮件发送功能都是如何设计和实现的。 阅读建议:此资源以开发简化版android基础组件、多线程学习其原理...
在android中界面要实时刷新数据,利用异步线程执行耗时操作,把执行后数据传给UI线程处理
我们需要根据字体的宽度设置在圆环中间,中间的进度百分比,先转换成float在进行除法运算,不然都为0,设置进度时,由于考虑多线的问题,需要同步刷新界面调用postInvalidate()能在非UI线程刷新。 本源码中的注释...
这致使我们不能在Android的UI线程中执行一些费时的操作,如下载、刷新等。Android中只允许UI线程对Activity中的UI组件进行修改。不过我们有两种方式来优化这种麻烦的情况——Handler和AsyncTack。
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 invalidate()是用来刷新View...
ANDROID 界面刷新 174 MESSAGE HANDER 175 用法: 175 线程与子线程调用MessageHander 177 Messagehandler实例 177 8、数据存储与读取 179 1. PREFERENCES 179 2. FILES 180 3. DATABASES 180 4. NETWORK 183 5、...
ANDROID 界面刷新 174 MESSAGE HANDER 175 用法: 175 线程与子线程调用MessageHander 177 Messagehandler实例 177 8、数据存储与读取 179 1. PREFERENCES 179 2. FILES 180 3. DATABASES 180 4. NETWORK 183 5、...
学完了这阶段课程,学员将学会开发主流网站的前端效果,比如:焦点图、滚动展示图、网页防复制、网页自定义菜单、WebOS、美女时钟、无刷新评论、评分控件、表格特效、图片悬浮详细信息、微博界面、QQ消息框效果、Div...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...