UI线程异常处理方法
当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程。其他线程叫工作线程(Work Thread)。
Single Thread Model
- 一个组件的创建并不会新建一个线程,他们的创建都在UI线程中进行,包括他们的回调方法,如onKeyDown()。
- 当在UI线程中进行某些耗时的操作时,将会阻塞UI线程,一般阻塞超过5秒就会显示一个ANR对话框(弹出程序无反应的对话框)。
- UI线程是非线程安全的,所以,不能在工作线程中操作UI元素。
两个原则
- Do not block the UI thread (不要阻塞UI线程)
- Do not access the Android UI toolkit from outside the UI thread (不要在工作线程中操作UI元素)
在工作线程更新UI方法
- Activity.runOnUiThread(Runnable)
- Handler
- sendMessage(Message)
- post(Runnable)
- AsyncTask
- execute()
- doInBackground()
- onPostExecute()
例子程序
- HandlerActivity01
- 在工作线程中进行UI操作。
- HandlerActivity02
- Handler的两个重要方法:sendMessage和post。
- HandlerActivity03
- 官方推荐最佳方法。
HandlerActivity01主要代码:
Java代码- btnEnd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- new Thread(new Runnable() {
- @Override
- public void run()
- {
- //在新建的线程(工作线程)中改变Button的文字
- btnEnd.setText("Text Changed in Sub Thread");
- }
- }).start();
- }
- });
这是一种错误的做法,运行程序,会报错误:
Java代码- android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
HandlerActivity02主要代码:
Java代码- public class HandlerActivity02 extends Activity
- {
- private int title = 0;
- Button btnStart,btnEnd;
- private Handler mHandler = new Handler()
- {
- public void handleMessage(Message msg)
- {
- //更新UI
- switch (msg.what)
- {
- case 1:
- updateTitle();
- break;
- }
- };
- };
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btnStart = (Button)findViewById(R.id.start);
- btnEnd = (Button)findViewById(R.id.end);
- //新启动一个线程,进行耗时操作
- Timer timer = new Timer();
- //每六秒执行一次MyTask的run方法
- timer.scheduleAtFixedRate(new MyTask(this), 1, 6000);
- }
- private class MyTask extends TimerTask
- {
- private Activity context;
- MyTask(Activity context)
- {
- this.context = context;
- }
- @Override
- public void run()
- {
- //耗时操作略....
- //更新UI方法 1
- Message message = new Message();
- message.what = 1;
- mHandler.sendMessage(message);
- //更新UI方法 2
- mHandler.post(updateThread);
- //更新UI方法 3
- context.runOnUiThread(updateThread);
- }
- }
- public void updateTitle()
- {
- setTitle("Welcome to Mr Wei's blog " + title);
- title++;
- }
- Runnable updateThread = new Runnable()
- {
- @Override
- public void run()
- {
- //更新UI
- btnStart.setText(String.valueOf(title));
- btnEnd.setText(String.valueOf(title));
- }
- };
- }
这里有个容易出错的地方,在更新UI方法2和3中,我们传入的参数是一个Runnable对象,一般认为这就会启动一个新的线程,而且常有人在这个Runnable对象的run方法中进行耗时操作。看过这块的源码就会知道,其实,android只是调用了这个Runnable对象的run方法而已,并没有启动新的线程,而且我们不应该在run方法中进行耗时操作,因为这个run方法最终是在UI线程里面执行的。也就是说,run方法里面只应该放更新UI的代码,handleMessage方法也一样。
如果你要看这部分源代码的话,相信这个图对你会有帮助:

HandlerActivity03主要代码:
Java代码- public class HandlerActivity03 extends Activity
- {
- Button btnStart;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btnStart = (Button)findViewById(R.id.start);
- btnStart.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //开始执行AsyncTask,并传入某些数据
- new LongTimeTask().execute("New Text");
- }
- });
- }
- private class LongTimeTask extends AsyncTask
- {
- @Override
- protected String doInBackground(String... params)
- {
- try
- {
- //线程睡眠5秒,模拟耗时操作,这里面的内容Android系统会自动为你启动一个新的线程执行
- Thread.sleep(5000);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- return params[0];
- }
- @Override
- protected void onPostExecute(String result)
- {
- //更新UI的操作,这里面的内容是在UI线程里面执行的
- btnStart.setText(result);
- }
- }
- }
这个方法确实挺好,因为它为你封装了许多操作,你只需要记住在doInBackground方法中写耗时操作的代码,在onPostExecute方法中写更新UI的方法就行了
UI线程异常处理方法的更多相关文章
- OkHttp3几个简单的例子和在子线程更新UI线程的方法
okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...
- java线程异常处理方法
工作中常发现有些程序发生异常但却没有错误日志,原因就是一些开发线程异常处理错误,导致程序报错但异常信息打印到堆栈上,不好在生产环境中定位问题. 在java多线程程序中,所有线程都不允许抛出未捕获的ch ...
- android在其他线程中访问UI线程的方法
1.Activity.runOnUiThread( Runnable ) 2.View.post( Runnable ) 3.View.postDelayed( Runnable, long ) 4. ...
- Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面
Android应用的开发过程中需要把繁重的任务(IO,网络连接等)放到其他线程中异步执行,达到不阻塞UI的效果. 下面将由浅入深介绍Android进行异步处理的实现方法和系统底层的实现原理. 本文介绍 ...
- Android异步处理系列文章四篇之一使用Thread+Handler实现非UI线程更新UI界面
目录: Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+L ...
- 关于 SWT 的UI线程和非UI线程
要理解UI线程,先要了解一下“消息循环”这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作都转化成为对应的消息,加入消息队列.然后把消息转发给对应的应用程序(一般来说,就是活动 ...
- 【插件式框架探索系列】使用多UI线程提升性能
了解WPF线程模型的都知道,UI线程负责呈现和管理UI,而UI元素(派生自 DispatcherObject)只能由创建该元素的线程来访问,这就导致了一些耗时的UI操作将影 响到整个应用程序性能,未响 ...
- Android子线程更新UI主线程方法之Handler
背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. ...
- WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )
WPF:谈谈各种多线程去修改或访问UI线程数据的方法http://www.cnblogs.com/mgen/archive/2012/03/10/2389509.html 子线程非法访问UI线程的数据 ...
随机推荐
- strcpy函数
不调用C/C++库函数,编写strcpy()函数. char * my_strcpy(char *strDest,const char *strSrc) { char *p=strDest; whil ...
- freemarker报错之十四
1.错误描述 <html> <head> <meta http-equiv="content-type" content="text/htm ...
- Jqurey 得到url参数 getUrlParam
Jqurey 得到url参数 getUrlParam <script type="text/javascript"> (function ($) { //扩展方法获取u ...
- 自用公共js文件
// 加载配置文件var instance = axios.create({ baseURL: 'http://zy-shop.tincent.me/Wechat/', headers: { 'Con ...
- 石子归并 51Nod - 1021
N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价.计算将N堆石子合并成一堆的最小代价. 例如: 1 2 3 4,有 ...
- freemark标签从后台接过来数据Boolean在前台还是Boolean输出(四)
FREEMARK标签中输出BOOLEAN值 private boolean showHeader=true; public boolean getShowHeader(){ return this.s ...
- RobotFramework自动化测试框架的基础关键字(二)
1.1.1 如何快速查询某一个关键字的API说明 鼠标选中我们关键字,同时按住Ctrl+Alt键,即可出来该关键字的帮助API以及使用示例 1.1.2 如何快速补全关键字 ...
- 【BZOJ1008】【HNOI2008】越狱(组合数学)
题面 题目描述 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 输入输出格式 ...
- 关于input 的选中,自定义input[type="checkbox"]样式
1.css 呈现 选中后 的input的样式可以用 /*背景图*/ background:url('../pc/images/archives/icon_choosed.png') no ...
- 使用glide进行包管理
glide是golang的一款包管理工具,就像Java下的Maven(当然Maven的定位不只是包管理工具).今天试用了一下,记录一下使用过程和遇到的一些坑. 环境 Windows 7,Goland, ...