`

android编程之在单线程模型中Message、Handler、Message Queue、Looper之间的关系

 
阅读更多

 1. Android进程
  在了解Android线程之前得先了解一下Android的进程。当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。
  同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android 会尝试停止一些进程从而释放足够的资源给其他新的进程使用,也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别:
  前台进程
  前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说,在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
  可见进程
  可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
  服务进程
  运 行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
  后台进程
  运 行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
  空进程
  未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。
  Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程――特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。
  2. 单线程模型
  当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
  2.1 子线程更新UI
  Android的UI是单线程(Single-threaded)的。为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来执行UI对象,Android就会发出错误讯息
  CalledFromWrongThreadException。以后遇到这样的异常抛出时就要知道怎么回事了!
  2.2 Message Queue
  在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:
  1. Message
  Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
  2. Handler
  Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)
  方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
  3. Message Queue
  Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
  每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
  4. Looper
  Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper() 得到当前线程的Looper就有可能为NULL。
  对于子线程使用Looper,API Doc提供了正确的使用方法:
  这个Message机制的大概流程:
  1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
  2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。
  在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
  1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
  2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
  3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
  由此可见,我们实现的handleMessage方法是优先级最低的!
  3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!
  在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法判断Handler对象里面的 Looper对象是属于哪条线程的,则由该线程来执行!
  1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
  2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。
  现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:
  这个例子,我自己写完后觉得还是有点乱,要稍微整理才能看明白线程间交互的过程以及数据的前后变化。随后了解到AsyncTask类,相应修改后就很容易明白了!
  AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.
  AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.
  AIDL的创建方法:AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型

0
0
分享到:
评论

相关推荐

    Android单线程模型中Message、Handler、Message Queue、Looper之间的关系---附实例源码

    消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理,在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件...

    Thread,Looper,Handler,Message,MessageQueue,MessagePool之间的关系

    在Android系统中,线程(Thread)、Looper、Handler、Message以及MessageQueue和MessagePool是实现异步消息处理机制的关键组件,它们共同构建了一个高效的事件驱动模型。这些组件的关系紧密,协同工作,使得Android...

    Android的消息处理机制--Message,MessageQueue

    4. **Looper**:充当MessageQueue和Handler之间的桥梁角色,负责循环取出MessageQueue中的消息,并交给对应的Handler处理。 #### 四、消息处理流程 1. **创建Handler**:每个需要处理消息的线程都需要一个Handler...

    浅谈android线程模型

    1. **Handler与Message Queue**:使用`Handler`对象,可以在子线程中发送消息,由UI线程中的`Handler`接收并处理,以此更新UI。 2. **RunOnUiThread**:对于Activity或Fragment,可以使用`runOnUiThread(Runnable)`...

    Android Looper使用介绍

    Android Looper 是 Android 操作系统中的一种机制,用于在单线程中创建消息循环,以便实现线程之间的通信和消息处理。Looper 对象通过 MessageQueue 来存放消息和事件,每个线程只能有一个 Looper 对象,-...

    Android Handler机制的工作原理详析

    在Looper的loop()方法中,会不断地从MessageQueue中取出Message对象,并将其 dispatch 到对应的Handler对象中。 Handler是Android中的一个抽象类,负责处理消息的处理和分发。Handler对象可以attach到一个Looper...

    android——多线程

    Android系统默认运行在一个单线程环境中,即主线程,也被称为UI线程。主线程主要负责处理UI更新、用户交互事件。如果在主线程中执行耗时操作,应用程序将会出现“Application Not Responding”(ANR)错误,用户体验...

    handler消息机制完整版

    4. **Looper(循环器)**:Looper是消息队列和Handler之间的协调者,它在一个线程中循环读取Message Queue,取出Message并交给对应的Handler进行处理。主线程默认已经有一个Looper,而其他线程需要手动调用`Looper....

    线程,线程池与Handler的用法

    在Android开发中,线程和线程池是处理异步任务的重要工具,而Handler则是用于在主线程和子线程之间通信的关键组件。本篇文章将深入探讨这些概念,以及它们在实际应用中的用法。 首先,让我们理解什么是线程。线程是...

    Android多线程处理.pdf

    Android采用单线程模型来管理UI,所有与UI相关的操作都必须在主线程(也称为UI线程或main thread)中完成。 2. Android提供了线程间通信的机制,通过Handler可以将任务分发到其他线程去执行,然后回到主线程更新UI...

    Android多线程处理[归类].pdf

    当一个子线程需要更新UI时,它不能直接操作UI组件,而是通过创建一个Handler实例,然后在子线程中创建一个Message对象,将需要执行的UI更新操作放入Message中。接着,子线程调用Handler的sendMessage()方法将Message...

    深理解android 线程消息机制教程

    首先,我们要明白Android系统对应用程序的执行环境是单线程模型,即主线程(也称为UI线程)负责处理所有的用户交互和界面更新。然而,由于CPU的并行处理能力,开发者常常需要在后台执行耗时操作,如网络请求、数据库...

    Handler消息处理机制+面试说.md

    它通过一系列组件(包括`Handler`、`Looper`和`MessageQueue`)实现了一个异步消息队列,允许开发者在不同的线程之间传递消息或运行代码。 1. **单个线程内的`MessageQueue`**:每个线程都有一个独立的`Message...

    Handler机制详解

    总结来说,Handler机制是Android多线程编程的核心部分,它与Looper和MessageQueue一起确保了线程安全的消息传递和处理,使得开发者能够有效地在后台线程和主线程之间进行数据同步和UI更新。而AsyncTask则为开发者...

    Android消息机制

    在Android开发中,消息机制通过几个核心组件协作完成任务:Looper、Handler、Message和MessageQueue。 一、UI线程 Android应用启动时会创建一个主线程,也就是UI线程。UI线程是应用程序的入口,并且是唯一的,负责...

    Android Handle Thread.docx

    在Android系统中,线程管理是非常关键的一部分,...开发者需要掌握如何合理利用线程,避免阻塞UI线程,同时利用Message Queue、Handler和Looper实现后台线程与UI线程之间的安全通信,以提高应用的响应速度和用户体验。

    Android 消息处理机制原理 - 简书1

    在Android系统中,由于UI线程是单线程模型,所有的界面更新操作必须在主线程中执行,因此,当需要在子线程中处理耗时任务后更新UI时,就需要借助消息机制来实现。 Android的消息机制主要由四个组件构成:Handler...

    AndroidHandleThread[定义].pdf

    本文主要探讨了Android线程的概念,特别是主线程和其相关的单线程模型,以及如何通过Message Queue、Handler和Looper组件来实现线程间的通信。 首先,Android进程是应用的基础,每个Android应用程序都会运行在一个...

    安卓UI线程机制 ,在子线程中访问UI

    3. Handler:Handler是Android中进行线程间通信的关键组件,它与Looper和MessageQueue紧密关联。Handler可以发送Message到MessageQueue,同时也可以处理由Looper传递过来的消息。这样,即使任务在子线程中创建,也...

Global site tag (gtag.js) - Google Analytics