- 浏览: 439767 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
qja:
Iterator.remove()这个方法也会出错的。
java.util.ConcurrentModificationException 出现的原因和解决办法 -
angeli:
List<String> save = new A ...
java.util.ConcurrentModificationException 出现的原因和解决办法 -
大峰子:
灰常感谢 刚好碰到这个问题, 搜了好多都没找到解决方法
python学习笔记-Python交互模式下方向键出现乱码 -
anypwx:
牛哥,怎么找到的,解决了我的报错问题,谢谢
JSONObject NestableRuntimeException -
tp7300:
确实好很多了,谢谢博主。
Failed to install on device 'emulator-5554': timeout
作用:Android的线程间消息处理机制主要是用来处理主线程(UI线程)跟工作线程(自己创建的线程)间通信的,如:通过工作线程刷新界面,或者在工作线程中创建一个dialog或者Toast等。
工作线程:在android应用程序中,我们创建的Activity、Service、Broadcast等都是在主线程(UI线程)处理的,但一些比较耗时的操作,如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑创建一个工作线程(继承Thread类或者实现Runnable接口)来解决。
使用工作线程容易出现的问题:对于Android平台来说UI控件都没有设计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,否则使用工作线程更新UI会出现异常。
Looper:
针对以上问题,android采用消息循环机制来处理线程间的通信,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环),Android系统中Looper负责管理线程的消息队列和消息循环, 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的 Looper对象。Looper对象是什么呢?其实Android中每一个Thread都对应一个Looper,Looper可以帮助Thread维护一个消息队列,负责在多线程之间传递消息的一个循环器。一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。如下例所示:class LooperThread extends Thread {
public Handler mHandler; public void run() { Looper.prepare(); mHandler =newHandler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
Looper.prepare():Looper对象的创建是通过prepare函数,而且每一个Looper对象会和一个线程关联,具体操作请见源码:
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }
Looper对象创建时会创建一个MessageQueue(消息队列),主线程默认会创建一个Looper从而有MessageQueue,其他线程默认是没有 MessageQueue的,不能接收Message(消息),如果需要接收Message则需要通过prepare函数创建一个MessageQueue。具体操作请见源码。
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
Looper.loop():Loop函数从MessageQueue中从前往后取出Message,然后通过Handler的dispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),消息处理完了以后通过Message对象的recycle函数放到Message Pool中,以便下次使用,通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。至于需要定时处理的消息如何做到定时处理,请见 MessageQueue的next函数,它在取Message来进行处理时通过判断MessageQueue里面的Message是否符合时间要求来决定是否需要把Message取出来做处理,通过这种方式做到消息的定时处理。具体操作请见源码:
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message
return;
}
if (me.mLogging!= null)
me.mLogging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null)
me.mLogging.println("<<<<< Finished to" + msg.target + " "+ msg.callback);
msg.recycle();
}
}
}
看next()函数
final Message next() {
boolean tryIdle = true;
while (true) {
long now;
Object[] idlers = null;
// Try to retrieve the next message, returning if found.
synchronized (this) {
// is counted in milliseconds since the system was booted,not counting time spent in deep sleep.
now = SystemClock.uptimeMillis();
Message msg = pullNextLocked(now);
if (msg != null) return msg;
if (tryIdle && mIdleHandlers.size() > 0) {
idlers = mIdleHandlers.toArray();
}
}
// There was no message so we are going to wait... but first,
// if there are any idle handlers let them know.
boolean didIdle = false;
if (idlers != null) {
for (Object idler : idlers) {
boolean keep = false;
try {
didIdle = true;
keep = ((IdleHandler)idler).queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
}
// While calling an idle handler, a new message could have been
// delivered... so go back and look again for a pending message.
if (didIdle) {
tryIdle = false;
continue;
}
synchronized (this) {
// No messages, nobody to tell about it... time to wait!
try {
if (mMessages != null) {
if (mMessages.when-now > 0) {
Binder.flushPendingCommands();
this.wait(mMessages.when-now);
}
} else {
Binder.flushPendingCommands();
this.wait();
}
}
catch (InterruptedException e) {
}
}
}
}
final Message pullNextLocked(long now) { Message msg = mMessages; if (msg != null) { if (now >= msg.when) { mMessages = msg.next; if (Config.LOGV) Log.v( "MessageQueue", "Returning message: " + msg); return msg; } } return null; }
Handler:
这样你的线程就具有了消息处理机制了,在Handler中进行消息处理。Activity是一个UI线程(主线程),Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。Handler的作用是把消息加入特定的消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。 一个Activity中可以创建多个工作线程或者其他的组件,如果这些线程或者组件把他们的消息放入Activity的主线程消息队列,那么该消息就会在主线程中处理了。因为主线程一般负责界面的更新操作,所以这种方式可以很好的实现Android界面更新。那么另外一个线程怎样把消息放入主线程的消息队列呢?是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用 Handler的sendMessage,将会把消息放入主线程的消息队列。并且将会在主线程中调用该handler 的handleMessage方法来处理消息。
Message:
获取消息:直接通过Message的obtain方法获取一个Message对象或者直接new一个Message对象。源码如下
public final Message obtainMessage(int what, int arg1, int arg2, Object obj){
return Message.obtain(this, what, arg1, arg2, obj);
}
Message.obtain函数:从Message Pool中取出一个Message,如果Message Pool中已经没有Message可取则新建一个Message返回。
Message Pool:大小为10个 。
清理Message是Looper里面的loop函数指把处理过的Message放到Message的Pool里面去,如果里面已经超过最大值10个,则丢弃这个Message对象。
发送消息:通过MessageQueue的enqueueMessage把Message对象放到MessageQueue的接收消息队列中,源码如下:
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
线程如何处理MessageQueue中接收的消息:在Looper的loop函数中循环取出MessageQueue的接收消息队列中的消息,然后调用 Hander的dispatchMessage函数对消息进行处理,源码如下:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
参考:
http://www.android123.com.cn/androidkaifa/422.html
http://dev.10086.cn/cmdn/wiki/index.php?edition-view-2600-1.html
http://hi.baidu.com/dragon_eros/blog/item/6eaf600cb4e22f28e824881c.html
评论
ni de shu ru fa ye huai le?
发表评论
-
warning: libfmodex64.so, needed by ../../lib/linux/Debug/libcocosdenshion.so,
2012-03-13 01:20 2070linux环境下用cocos2d-x开发游戏时,遇到了 wa ... -
在工作线程中创建Toast
2011-10-14 18:11 3757在工作线程中创建Toast,代码如下: p ... -
GridView + ViewFlipper布局界面,模仿“机锋市场”
2011-10-09 18:22 2284源码在附件中,效果如图片 -
fedora14下连接android真机
2011-08-13 13:22 1423在fedora14下搭建好了andro ... -
fedora14下搭建Android开发环境
2011-07-12 23:59 2589一:下载linux版本的JDK,Eclipse,Andr ... -
Android中ImageButton实现“按下”效果
2011-06-16 12:26 7687使用Button的时候,实现“按下”的效果是很重要的,也 ... -
Android实现TCP与UDP传输
2011-05-21 14:50 5430关于TCP和UDP协议的描述,可参考http://zho ... -
android textview改变部分文字的颜色和string.xml中文字的替换
2011-05-18 18:49 17319一:TextView组件改变部分文字的颜色: Text ... -
AndroiManifest.xml文件中android属性
2011-05-16 11:59 1454android:allowTaskReparentin ... -
windows系统上安装与使用Android NDK r5
2011-01-26 13:17 11378windows系统上安装与使用Android NDK r ... -
android获取屏幕分辨率
2011-01-15 17:05 2137获取屏幕分辨率的代码: ... -
Android编译出现Multiple substitutions specified in non-positional format
2010-12-31 13:28 3951前段时间更新了ADT和Android SDK 2.3, ... -
TextView设置中文粗体
2010-12-30 13:25 5526在xml布局文件中设置android:textStyle=“b ... -
Failed to install on device 'emulator-5554': timeout
2010-12-20 10:41 6230Failed to install on device ... -
解决android logcat不打印信息
2010-11-30 19:06 7940用eclipse进行android开发中经常遇到logcat无 ... -
关于android设备的分辨率
2010-11-29 12:27 1998HVGA (Half-size VGA) 即VGA ... -
Toast的用法
2010-11-18 13:28 4623Toast是android中用来显示快速显示短信息的一种机制, ... -
listview的美化和优化
2010-11-17 13:54 4379在android开发中,listview是比较常用的一个组件, ... -
activity切换特效(类似iphone的进入和退出时的效果)
2010-11-10 23:11 3926关于activity的切换,有很多挺好看的动画实现,最近在项目 ... -
美化listview时遇到的问题
2010-11-08 08:39 2562在android开发中,listview的默认背景颜 ...
相关推荐
`Looper`维持着消息循环,不断地从队列中取出消息并分发,而`Handler`则负责创建、发送和处理这些消息,实现了线程间的通信和同步。这种机制使得开发者能够在不阻塞主线程的情况下执行耗时操作,保证了UI的流畅性。...
Android 应用程序中,消息处理机制是其异步编程的核心组成部分,主要涉及三个关键组件:Handler、Message和Looper。这种机制使得应用可以有效地管理线程间的通信,避免阻塞主线程,提升用户体验。 首先,我们需要...
在有 Looper 的线程中,我们可以使用 Handler 来发送和处理消息。Handler 是一个抽象的概念,它可以将消息发送到 Looper 中,并且可以处理 Looper 中的消息。 Android 中的多线程模型可以分为以下几种: 1. 主线程...
这不, 前几天为了了解android的消息处理机制, 我看 了Looper, Handler, Message这几个类的源码, 结果又一次被googler的设计震撼了, 特与大家分享。 android的消息处理有三个核心类: Looper,Handler和Message...
在Android系统中,线程(Thread)、Looper、Handler、Message以及MessageQueue和MessagePool是实现异步消息处理机制的关键组件,它们共同构建了一个高效的事件驱动模型。这些组件的关系紧密,协同工作,使得Android...
`Handler`、`Message`和`Looper`是Android系统提供的一个关键机制,用于在不同的线程间进行通信,特别是主线程(UI线程)与工作线程间的交互。下面将详细解释这三个组件以及它们如何协同工作。 1. **Handler...
消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理,在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件...
【Android异步消息处理机制】深入理解Looper、Handler、Message三者关系 在Android系统中,异步消息处理机制是实现线程间通信和保证UI线程安全的关键组件。它涉及到了三个核心类:Looper、Handler和Message。这篇...
总的来说,Android的消息处理机制是一个高效、灵活的工具,它使得开发者能够优雅地处理异步事件和线程间的通信,是构建高性能Android应用的基础。通过对Looper、Handler和Message的深入理解,开发者可以更好地掌控...
这就是 Android 的异步处理机制,其中 Handler、Looper 和 MessageQueue 是关键组件,它们共同构成了 Android 线程间通信的基础。 1. **Handler**: Handler 是一个接口,用于发送和处理消息。它与 Looper 关联,...
在主线程即UI线程外,新建一个Looper线程,并用Messenger和Handler来处理message和posted runnable。程序中,在负线程中默认加了一个3s的线程等来,来帮助理解sent message和post runnable之间的同步机制。所以在按...
在 Android 中,多线程机制是基于 Handler 和 Message 机制的。 Handler 是什么?Handler 是一个处理器,它负责处理和绑定到该 Handler 的线程中的 Message。每一个 Handler 都必须关联一个 Looper,并且两者是一一...
### Message,MessageQueue,Looper,Handler详解 #### 一、几个关键概念 ...通过它们之间的相互协作,使得应用程序能够在不同的线程间高效地传递和处理消息,从而实现了复杂的用户交互逻辑和后台任务处理等功能。
本文详细介绍了Android中消息处理机制的核心组件Looper、MessageQueue和Handler的工作原理及其实现细节。理解这些概念有助于开发者更好地设计和实现多线程应用程序,提高程序的性能和用户体验。通过合理利用这些组件...
Handler和Looper是Android系统中两个非常重要的组件,它们之间相互关联,共同实现了Android系统中的消息处理机制。在本文中,我们将对Handler和Looper进行详细的解释,并探讨它们在Android系统中的作用。 一、...
在Android系统中,Handler、Looper和MessageQueue是实现线程间通信的核心组件,它们共同构建了一个消息处理机制。本文将深入解析这三者的源码,帮助你理解它们的工作原理,并教你如何手写一套自己的Handler系统。 ...
通过以上介绍可以看出,Android的Message机制是通过`Handler`、`Message`、`Looper`和`MessageQueue`四个关键组件协同工作来完成的。这种机制不仅使得应用程序内部通信变得更加高效有序,同时也为开发者提供了一种...
Handler是Android中的一个类,它主要用于发送和处理Message对象。在主线程(UI线程)中创建一个Handler实例后,我们可以在这个Handler中发送Message到Message Queue,然后由Looper取出并分发给相应的Handler进行处理...
`Handler`的主要作用是在Android的消息队列中发送和处理消息。它的核心流程主要包括三部分:`Handler`对象、`Looper`循环器和`Message`消息对象。首先,我们需要创建一个`Handler`实例,这个实例通常在UI线程中创建...
在Android系统中,Handler、Message和Looper构成了一个关键的异步通信机制,即Handler消息处理机制。这个机制允许Android应用程序在不同的线程间传递消息,处理UI更新等操作,是多线程编程中的重要组成部分。下面...