- 浏览: 47759 次
- 性别:
- 来自: 上海
最新评论
-
hanxie1121:
书读多了
思考一下!!!!my android -
huyong479072052:
不用说应届毕业生了,现在中国搞android的开发的有几个能达 ...
思考一下!!!!my android -
zhanhao:
顶!
思考一下!!!!my android -
cectsky:
你妈喊你回家吃饭
回调(callback)方法
熟悉Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息循环系统。而Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制。实际上谷歌参考了Windows的消息循环机制,也在Android系统中实现了消息循环机制。Android通过 Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环)。本文深入介绍一下 Android消息处理系统原理。
Android系统中Looper负责管理线程的消息队列和消息循环,具体实现请参考Looper的源码。 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的 Looper对象。
前面提到Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。如下例所示:
这样你的线程就具有了消息处理机制了,在Handler中进行消息处理。
Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。详细实现请参考ActivityThread.java文件。
Handler的作用是把消息加入特定的(Looper)消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。详细实现请参考Looper的源码。
Activity、Looper、Handler的关系如下图所示:
一个Activity中可以创建多个工作线程或者其他的组件,如果这些线程或者组件把他们的消息放入Activity的主线程消息队列,那么该消息就会在主线程中处理了。因为主线程一般负责界面的更新操作,并且Android系统中的wiget不是线程安全的,所以这种方式可以很好的实现Android界面更新。在Android系统中这种方式有着广泛的运用。
那么另外一个线程怎样把消息放入主线程的消息队列呢?答案是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用 Handler的sendMessage等接口,将会把消息放入队列都将是放入主线程的消息队列。并且将会在Handler主线程中调用该handler 的handleMessage接口来处理消息。
这里面涉及到线程同步问题,请先参考如下例子来理解Handler对象的线程模型:
1、首先创建MyHandler工程。
2、在MyHandler.java中加入如下的代码:
在这个例子中我们主要是打印,这种处理机制各个模块的所处的线程情况。如下是我的机器运行结果:
09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1
09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8
09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1
我们可以看出消息处理是在主线程中处理的,在消息处理函数中可以安全的调用主线程中的任何资源,包括刷新界面。工作线程和主线程运行在不同的线程中,所以必须要注意这两个线程间的竞争关系。
上例中,你可能注意到在工作线程中访问了主线程handler对象,并在调用handler的对象向消息队列加入了一个消息。这个过程中会不会出现消息队列数据不一致问题呢?答案是handler对象不会出问题,因为handler对象管理的Looper对象是线程安全的,不管是加入消息到消息队列和从队列读出消息都是有同步对象保护的,具体请参考Looper.java文件。上例中没有修改handler对象,所以handler对象不可能会出现数据不一致的问题。
通过上面的分析,我们可以得出如下结论:
1、如果通过工作线程刷新界面,推荐使用handler对象来实现。
2、注意工作线程和主线程之间的竞争关系。推荐handler对象在主线程中构造完成(并且启动工作线程之后不要再修改之,否则会出现数据不一致),然后在工作线程中可以放心的调用发送消息SendMessage等接口。
3、除了2所述的hanlder对象之外的任何主线程的成员变量如果在工作线程中调用,仔细考虑线程同步问题。如果有必要需要加入同步对象保护该变量。
4、handler对象的handleMessage接口将会在主线程中调用。在这个函数可以放心的调用主线程中任何变量和函数,进而完成更新UI的任务。
5、Android很多API也利用Handler这种线程特性,作为一种回调函数的变种,来通知调用者。这样Android框架就可以在其线程中将消息发送到调用者的线程消息队列之中,不用担心线程同步的问题。
深入理解Android消息处理机制对于应用程序开发非常重要,也可以让你对线程同步有更加深刻的认识。
Android系统中Looper负责管理线程的消息队列和消息循环,具体实现请参考Looper的源码。 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的 Looper对象。
前面提到Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。如下例所示:
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
这样你的线程就具有了消息处理机制了,在Handler中进行消息处理。
Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。详细实现请参考ActivityThread.java文件。
Handler的作用是把消息加入特定的(Looper)消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。详细实现请参考Looper的源码。
Activity、Looper、Handler的关系如下图所示:
一个Activity中可以创建多个工作线程或者其他的组件,如果这些线程或者组件把他们的消息放入Activity的主线程消息队列,那么该消息就会在主线程中处理了。因为主线程一般负责界面的更新操作,并且Android系统中的wiget不是线程安全的,所以这种方式可以很好的实现Android界面更新。在Android系统中这种方式有着广泛的运用。
那么另外一个线程怎样把消息放入主线程的消息队列呢?答案是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用 Handler的sendMessage等接口,将会把消息放入队列都将是放入主线程的消息队列。并且将会在Handler主线程中调用该handler 的handleMessage接口来处理消息。
这里面涉及到线程同步问题,请先参考如下例子来理解Handler对象的线程模型:
1、首先创建MyHandler工程。
2、在MyHandler.java中加入如下的代码:
package com.simon; import android.app.Activity; import android.os.Bundle; import android.os.Message; import android.util.Log; import android.os.Handler; public class MyHandler extends Activity { static final String TAG = "Handler"; Handler h = new Handler(){ public void handleMessage (Message msg) { switch(msg.what) { case HANDLER_TEST: Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "\n"); break; } } }; static final int HANDLER_TEST = 1; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "\n"); new myThread().start(); setContentView(R.layout.main); } class myThread extends Thread { public void run() { Message msg = new Message(); msg.what = HANDLER_TEST; h.sendMessage(msg); Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "\n"); } } }
在这个例子中我们主要是打印,这种处理机制各个模块的所处的线程情况。如下是我的机器运行结果:
09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1
09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8
09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1
我们可以看出消息处理是在主线程中处理的,在消息处理函数中可以安全的调用主线程中的任何资源,包括刷新界面。工作线程和主线程运行在不同的线程中,所以必须要注意这两个线程间的竞争关系。
上例中,你可能注意到在工作线程中访问了主线程handler对象,并在调用handler的对象向消息队列加入了一个消息。这个过程中会不会出现消息队列数据不一致问题呢?答案是handler对象不会出问题,因为handler对象管理的Looper对象是线程安全的,不管是加入消息到消息队列和从队列读出消息都是有同步对象保护的,具体请参考Looper.java文件。上例中没有修改handler对象,所以handler对象不可能会出现数据不一致的问题。
通过上面的分析,我们可以得出如下结论:
1、如果通过工作线程刷新界面,推荐使用handler对象来实现。
2、注意工作线程和主线程之间的竞争关系。推荐handler对象在主线程中构造完成(并且启动工作线程之后不要再修改之,否则会出现数据不一致),然后在工作线程中可以放心的调用发送消息SendMessage等接口。
3、除了2所述的hanlder对象之外的任何主线程的成员变量如果在工作线程中调用,仔细考虑线程同步问题。如果有必要需要加入同步对象保护该变量。
4、handler对象的handleMessage接口将会在主线程中调用。在这个函数可以放心的调用主线程中任何变量和函数,进而完成更新UI的任务。
5、Android很多API也利用Handler这种线程特性,作为一种回调函数的变种,来通知调用者。这样Android框架就可以在其线程中将消息发送到调用者的线程消息队列之中,不用担心线程同步的问题。
深入理解Android消息处理机制对于应用程序开发非常重要,也可以让你对线程同步有更加深刻的认识。
发表评论
-
android 4.0 取内外置SD卡新特性
2013-06-06 12:44 1161private StorageManager mStorage ... -
android 2.3 取内外置SD卡
2013-06-06 12:42 1922在android2.3中 判断内置SD卡是否挂载: if( ... -
android 关闭数据连接方法
2013-05-04 21:18 1584开关数据连接方法: Method getITelepho ... -
Activity Task Task 栈
2011-12-03 15:30 11241、Activity和Task task就好像是能包含很多a ... -
判断Android 网络状态
2011-12-03 11:53 922当需要开启Activity之前需要检测网络状态的时候需要用到一 ... -
LauncherEx UI初探及Drag机制了解
2011-11-23 10:34 1见下载!! -
Android APK签名
2011-11-23 10:30 13421.签名的意义 为了保证每个应用程序开发商合法ID,防止部 ... -
Android 横竖屏设置
2011-11-17 09:03 1132最近遇到一个问题,关于Android 横竖屏的问题,我的lau ... -
Android 设计之流畅设计
2011-11-14 20:42 765即使你的应用程序是快速且响应灵敏的,但一些设计仍然会给用户造成 ... -
Android_WindowManager分析
2011-11-02 13:53 1Activity 建立一个主窗口 ... -
onInterceptTouchEvent和onTouchEvent调用时序
2011-10-22 17:01 821onInterceptTouchEvent()是ViewGro ... -
activity 启动方式
2011-10-15 11:15 846在android里,有4种activity ... -
Android功能总结:仿照Launcher的Workspace实现左右滑动切换
2011-10-09 17:36 2294对于Launcher的桌面滑动大家应该都比较熟悉了,最好的体验 ... -
Android中的Handler, Looper, MessageQueue和Thread
2011-10-08 20:34 1166前几天,和同事探讨了一下Android中的消息机制,探究了消息 ... -
ListView 动态加载
2011-09-29 20:46 1190ListView的动态加载,想必大家在网上都看过很多资料了。我 ... -
AppWidget加载流程(二)
2011-09-27 17:38 9401. 用户长按Launcher弹出添快捷组件的Dialog,选 ... -
AppWidget加载流程(一)
2011-09-27 17:34 12611. Android系统启动,SystemServer创建A ... -
Android(安卓) snippet
2011-09-21 10:33 01.获取屏幕的分辨率 在 activity 里利用如下编码,宽 ... -
Android 中Locale,auto-rotate状态的获取
2011-09-21 10:26 15391. 得到当前locale: Context.getReso ... -
理解Android系统的进程间通信原理(一)----RPC中的代理模式
2011-09-14 19:39 1068[size=medium]理解Android系统的进程间通信原 ...
相关推荐
本篇文章将深入探讨Android中消息处理的核心组件——Looper、MessageQueue、Handler以及消息循环的工作原理。理解这些概念对于构建响应迅速、用户友好的应用程序至关重要。 #### 二、核心概念 ##### 1. Looper ...
深入理解Android 卷1 不是扫描版的,是全版电子书的,非PDF,可编辑,各种阅览器以打开!包括书签和同步目录! 第1章 阅读前的准备工作 / 1 1.1 系统架构 / 2 1.1.1 Android系统架构 / 2 1.1.2 本书的架构 / 3 1.2 ...
标题"android——多线程"和描述"android——Handler与多线程应用范例"暗示我们将深入探讨如何在Android中使用Handler来管理多线程。 Android系统默认运行在一个单线程环境中,即主线程,也被称为UI线程。主线程主要...
Android系统开发工程师常常需要深入理解系统的运转过程,而本书所涉及的内容可能正是他们在工作和学习中最想了解的。那些对具体模块(如Audio系统和Surface系统)感兴趣的读者 也可以直接阅读相关章节的内容。 ...
本篇文章将深入探讨Android Studio中的线程管理,即“Thread”主题。 在Android应用开发中,线程是执行任务的基本单元。由于Android系统的主线程(UI线程)主要负责处理用户界面交互,因此,为了保持UI的流畅性,...
5. **线程与定时器**:为了保证游戏流畅运行,通常会使用Handler和Looper机制或者单独的Thread(线程)来处理游戏逻辑。定时器(如TimerTask)则用来控制游戏的更新频率,比如每秒更新屏幕状态,确保蛇的移动和食物...
1. **Handler**:负责向消息队列发送消息和处理消息。 2. **MessageQueue**:存储由Handler发送的消息,等待Looper去循环读取并处理。 3. **Looper**:每一个线程中只有一个Looper实例,负责不断从MessageQueue中...
Handler是Android系统中用于线程间通信的关键组件,它允许开发者在不同的线程之间发送和处理消息。Message对象是Handler用来传递信息的数据载体,而Looper则是负责在特定线程中循环地取出Message并交给Handler处理的...
首先,Handler是Android中的一个关键类,它允许开发者在不同的线程之间发送和处理消息。Handler的实例通常与特定的线程关联,当通过Handler发送一个Message时,这个Message就会被添加到与该Handler关联的Message...
由于Android主线程负责UI更新,所以后台任务通常通过IntentService、AsyncTask、Thread或Handler/Looper机制进行。理解这些机制能避免ANR(应用无响应)问题,提升应用性能。 “c9”和“c10”可能涉及更高级的主题...
无论哪种方式,接收和处理消息的Handler必须在同一线程中,否则会抛出异常。 总结起来,Android线程消息机制是通过Handler、Looper和Message的协同工作,实现线程间的异步通信和任务调度。理解并熟练运用这一机制,...
这涉及到Android的Thread、AsyncTask或者Handler/Looper机制。 7. **音频与图形处理**:在游戏开发中,音频和图形处理是重要部分。Android提供了MediaPlayer和SoundPool处理音频,而2D图形通常通过Canvas和Paint类...
【标题】:“安卓Android源码——蓝牙聊天的.zip”提供了Android平台上实现蓝牙聊天功能的源代码,这是一份深入理解Android蓝牙通信机制的宝贵资源。通过这份源码,开发者可以学习到如何在Android设备间建立蓝牙连接...
### Android高级开发面试题——Handler相关知识 #### 一、HandlerLooperMessage关系 **1. Handler、Looper与Message之间的关系** - **Handler**: 主要用于发送消息和处理消息。它作为一个桥梁,使得主线程和子...
这涉及到Android的Handler、Looper和Thread的使用,以及异步任务的处理。 3. **动态加载歌词**:应用可能需要从网络或者本地资源中加载歌词,这涉及到HTTP请求、JSON解析(如果歌词数据以JSON格式存储)以及SQLite...
它们在主线程中处理消息和回调,如果在工作线程中使用了Handler,记得在结束线程前关闭Looper,以防止内存泄漏和资源占用。 总结,结束Android线程时,关键在于优雅、安全地中断操作,而不是简单粗暴地停止。合理的...
- Handler/Looper/Message:这是Android特有的异步处理机制,通过创建Handler,关联到特定线程的Looper,然后通过发送Message来执行异步任务。 3. 多线程核心机制——Handler/Looper/Message Handler、Looper和...