Android主线程如何向分java多线程发送消息息

&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Android子线程向主线程发送消息实现
摘要:在Android中开发应用的过程中,经常会遇到一些比较耗时的操作,比如网络请求、读取文件等操作。由于Android有一种ANR机制,UI线程阻塞超过5s就会报ANR错误。因此这些耗时的操作需要在子进程里去做。单起一个子线程去做耗时操作,可以解决ANR问题。但同时还有一个问题,就是子线程完成了操作,如何通知主线程即UI线程去做UI方面的更改。这就用到Handler。&&此处讲解的是子线程向主线程发送消息。与主线程向子线程发送消息有所不同。&&nbs
在Android中开发应用的过程中,经常会遇到一些比较耗时的操作,比如网络请求、读取文件等操作。由于Android有一种ANR机制,UI线程阻塞超过5s就会报ANR错误。因此这些耗时的操作需要在子进程里去做。单起一个子线程去做耗时操作,可以解决ANR问题。但同时还有一个问题,就是子线程完成了操作,如何通知主线程即UI线程去做UI方面的更改。这就用到Handler。& & 此处讲解的是子线程向主线程发送消息。与主线程向子线程发送消息有所不同。& &&
& & Handler mHandler = new Handler(){& & & & & & & &&& & & & & & public void HandleMessage(Message msg){& & & & & & & & & & super.HandleMessage(msg);& & & & & & & & & & switch(msg.what){& & & & & & & & & & & & & & case 0:& & & & & & & & & & & & & & & & & & & & //Todo something for UI;& & & & & & & & & & & & & & & & & & & && & & & & & & & & & } & & && & & & & & }& & };& & new Thread(){& & & & & & public void run(){& & & & & & & & & &&& & & & & & & & & & //Todo something. for example,Time-consuming events.& & & & & & & & & & Message msg = mHandler.obtainMessage();& & & & & & & & & & msg.arg1 = 0;& & & & & & & & & & mHandler.sendMessage(msg);& & & & & & }& & }.start();
参考:http://ask.android-studio.org/?/article/101
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Android子线程向主线程发送消息实现相关信息,包括
的信息,所有Android子线程向主线程发送消息实现相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
InternationalTA的最新馆藏[转]&[转]&[转]&
喜欢该文的人也喜欢查看:4832|回复:4
资深技术经理
Toast在android里面弹的很多了,但是在分线程里面弹会怎么样呢? 有些同学会说,那还不是和平时一样的弹?!其实,也不尽然,不信?请继续往下面看。
二 分线程弹Toast引发的问题
如果在分线程里面直接弹Toast,比如下面这样,button点击的时候启动一个线程,弹出一个Toast:
(21.06 KB)
那么就会得到一个应用程序异常终止的错误弹窗。
原因如下:复制内容到剪贴板代码:E/AndroidRuntime( 8978): FATAL EXCEPTION: Thread-2221
E/AndroidRuntime( 8978): Process: com.example.androidtest, PID: 8978
E/AndroidRuntime( 8978): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime( 8978):& && && &at android.os.Handler.&init&(Handler.java:200)
E/AndroidRuntime( 8978):& && && &at android.os.Handler.&init&(Handler.java:114)
E/AndroidRuntime( 8978):& && && &at android.widget.Toast$TN.&init&(Toast.java:347)
E/AndroidRuntime( 8978):& && && &at android.widget.Toast.&init&(Toast.java:100)
E/AndroidRuntime( 8978):& && && &at android.widget.Toast.makeText(Toast.java:254)
E/AndroidRuntime( 8978):& && && &at com.example.androidtest.MainActivity$1$1.run(MainActivity.java:40)
E/AndroidRuntime( 8978):& && && &at java.lang.Thread.run(Thread.java:818)
D/ActivityManager(&&939): addErrorToDropBox processName = com.example.androidtest意思是如果没有调用Looper.prepare(),就不能初始化Handler对象。看错误堆栈,是Toast.makeText()的时候会初始化Handler对象。
这个调用过程如下:
1. 从Toast.makeText(...)开始public static Toast makeText(Context context, CharSequence text, int duration) {
& && &&&Toast result = new Toast(context);
& && &&&...
& & }它会初始化一个Toast对象,继续看Toast的构造函数:
2.public Toast(Context context) {
& && &&&mContext =
& && &&&mTN = new TN();
& && &&&...
& & }在Toast的构造函数里面,会初始化一个TN对象,这个TN对象是什么东西呢?
3.private static class TN extends ITransientNotification.Stub {
final Handler mHandler = new Handler();& &
}这个TN对象是Binder对象的子类,显而易见,它是跨进程通信用的。其实它就是和系统Toast服务通信用的,应用程序需要把自己的Toast请求发送给系统Toast服务,告诉它,我需要弹一个什么样的Toast。
所以需要TN这个东东。
而TN这个东东需要初始化Handler成员变量,所以就会调用到Handler初始化这边。
4.&&Handler初始化public Handler(Callback callback, boolean async) {
& && &&&mLooper = Looper.myLooper();
& && &&&if (mLooper == null) {
& && && && &throw new RuntimeException(
& && && && && & &Can't create handler inside thread that has not called Looper.prepare()&);
& & }Handler初始化的时候会拿出与当前线程相关的Looper对象,如果不存在,也就是没有调用过Looper.prepare()方法的话,就会报错。
这就是上面错误的来源啦!
三 如何解决?
知道原因后,就比较好解决了,于是就出现了下面的代码:
(37.61 KB)
在分线程弹出Toast之前把Looper准备好,实验表明,这样确实可以达到效果。可以把Toast弹出来。
但是这样有个问题,就是会导致分线程永远不会退出。这个原理大家看看Looper.loop()是怎么实现的就知道了,它里面是一个死循环。
这样的话,会导致进程里面的线程越来越多,这个本人是不推荐的。
四 另外一种解决方法
除了第三种方法之外,我们还有种方法,就是把Toast丢到主线程去弹出来。
也很简单,主要初始化一个主线程的Handler,然后调用Handler.postRunnable()方法就可以了。,如下:
(39.85 KB)
这种方法其实也很符合Android的设计理念,就是UI相关的东东都让主线程去负责。繁琐的事情开启分线程完成。
其实解决方法挺简单的,只是想说的是,大家以后遇到问题一定要多多研究源代码,然后从中找到根本原因;最后拿出一种最合适的方法。既可以达到效果,又不会影响程序性能。
本帖最后由 rongwei84n 于
11:50 编辑
资深技术经理
资深技术经理
很好、赞一个、
只是、源码呢
太阳光芒万丈却不及蜡烛只为一人照亮、、、
资深技术经理
引用:原帖由 IT妖姬 于
21:35 发表
很好、赞一个、
只是、源码呢 源码自己写下吧,很简单的拉。。没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!博客分类:
在一个Android
程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的Activity或者Service(Service和
Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast
Receiver)都会跑在这个Process。
一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread。
在这么多Thread当中,有一个Thread,我们称之为UI Thread。UI
Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main
Thread,主要是负责控制UI界面的显示、更新和控件交互。在Android程序创建之初,一个Process呈现的是单线程模型,所有的任务都在一
个线程中运行。因此,我们认为,UI
Thread所执行的每一个函数,所花费的时间都应该是越短越好。而其他比较费时的工作(访问网络,下载数据,查询数据库等),都应该交由子线程去执行,
以免阻塞主线程。
那么,UI Thread如何和其他Thread一起工作呢?常用方法是:
诞生一个主线程的Handler物件,当做Listener去让子线程能将讯息Push到主线程的Message Quene里,以便触发主线程的handlerMessage()函数,让主线程知道子线程的状态,并在主线程更新UI。
例如,在子线程的状态发生变化时,我们需要更新UI。如果在子线程中直接更新UI,通常会抛出下面的异常:
11-07 13:33:04.393:
ERROR/JavaBinder(1029):android.view.ViewRoot$CalledFromWrongThreadException:Only
the original thread that created a view hierarchy can touch its views.
意思是,无法在子线程中更新UI。为此,我们需要通过Handler物件,通知主线程Ui Thread来更新界面。
如下,首先创建一个Handler,来监听Message的事件:
private final int UPDATE_UI = 1;
private Handler mHandler = new MainHandler();
private class MainHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_UI: {
Log.i("TTSDeamon", "UPDATE_UI");
showTextView.setText(editText.getText().toString());
ShowAnimation();
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_UI: {
Log.i("TTSDeamon", "UPDATE_UI");
showTextView.setText(editText.getText().toString());
ShowAnimation();
当子线程的状态发生变化,则在子线程中发出Message,通知更新UI。
mHandler.sendEmptyMessageDelayed(UPDATE_UI, 0);
在我们的程序中,很多Callback方法有时候并不是运行在主线程当中的,所以如果在Callback方法中更新UI失败,也可以采用上面的方法。
浏览 49081
浏览: 1406820 次
来自: 上海
有demo吗?
推荐给大家一些有用的爬虫源码:https://github.c ...
除了.classpath文件以外,.project文件也应该了 ...
造成eclipse自动关闭的原因有很多,这里有很多介绍:ecl ...
网上都是这些,这种文章。。。
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 多线程发送消息 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信