`

android线程相关1

 
阅读更多

 

android中的Handler
对于这部分的内容,将分成4 小节来描述:
1)职责与关系
2)消息循环
3)线程与更新
4)几点小结
----------------------------------------------------------------------------------------------
1) 接下来,我们开始这部分的内容,首先了解一下各自的职责及相互之间的关系。
职责
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue 统一列队,终由               Handler 处理。
Handler:处理者,负责Message 的发送及处理。使用Handler 时,需要实现handleMessage(Message msg)      方法来对特定的Message 进行处理,例如更新UI 等。
MessageQueue:消息队列,用来存放Handler 发送过来的消息,并按照FIFO 规则执行。当然,存放Message      并非实际意义的保存,而是将Message 以链表的方式串联起来的,等待Looper 的抽取。
Looper:消息泵,不断地从MessageQueue 中抽取Message 执行。因此,一个MessageQueue 需要一Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

关系
    class Class Model
    Looper MessageQueue
    Handler
Handler,Looper 和MessageQueue 就是简单的三角关系。Looper 和MessageQueue 一
一对应,创建一个Looper 的同时,会创建一个MessageQueue。而Handler 与它们的关
系,只是简单的聚集关系,即Handler 里会引用当前线程里的特定Looper 和MessageQueue。
这样说来,多个Handler 都可以共享同一Looper 和MessageQueue 了。当然,这些
Handler 也就运行在同一个线程里。

2) 接下来,我们简单地看一下消息的循环过程:
生成
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.sendToTarget();

发送
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
在Handler.java 的sendMessageAtTime(Message msg, long uptimeMillis)方法中,我们看
到,它找到它所引用的MessageQueue,然后将Message 的target 设定成自己(目的是
为了在处理消息环节,Message 能找到正确的Handler),再将这个Message 纳入到消
息队列中。

抽取
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
在Looper.java 的loop()函数里,我们看到,这里有一个死循环,不断地从
MessageQueue 中获取下一个(next 方法)Message,然后通过Message 中携带的
target 信息,交由正确的Handler 处理(dispatchMessage 方法)。

处理
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
在Handler.java 的dispatchMessage(Message msg)方法里,其中的一个分支就是调用
handleMessage方法来处理这条Message,而这也正是我们在职责处描述使用Handler
时需要实现handleMessage(Message msg)的原因。
至于dispatchMessage 方法中的另外一个分支,我将会在后面的内容中说明。
至此,我们看到,一个Message 经由Handler 的发送,MessageQueue 的入队,Looper
的抽取,又再一次地回到Handler 的怀抱。而绕的这一圈,也正好帮助我们将同步操作
变成了异步操作。

3)剩下的部分,我们将讨论一下Handler 所处的线程及更新UI 的方式。
在主线程(UI 线程)里,如果创建Handler 时不传入Looper 对象,那么将直接使用主
线程(UI 线程)的Looper 对象(系统已经帮我们创建了);在其它线程里,如果创建
Handler 时不传入Looper 对象,那么,这个Handler 将不能接收处理消息。在这种情况
下,通用的作法是:
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 之前,为该线程准备好一个Looper(Looper.prepare),然后让这个
Looper 跑起来(Looper.loop),抽取Message,这样,Handler 才能正常工作。
因此,Handler 处理消息总是在创建Handler 的线程里运行。而我们的消息处理中,不
乏更新UI 的操作,不正确的线程直接更新UI 将引发异常。因此,需要时刻关心
Handler 在哪个线程里创建的。

如何更新UI 才能不出异常呢?SDK 告诉我们,有以下4 种方式可以从其它线程访问UI
线程:
· Activity.runOnUiThread(Runnable)
· View.post(Runnable)
· View.postDelayed(Runnable, long)
· Handler
其中,重点说一下的是View.post(Runnable)方法。在post(Runnable action)方法里,
View 获得当前线程(即UI 线程)的Handler,然后将action 对象post 到Handler 里。
在Handler 里,它将传递过来的action 对象包装成一个Message(Message 的callback
为action),然后将其投入UI 线程的消息循环中。在Handler 再次处理该Message 时,
有一条分支(未解释的那条)就是为它所设,直接调用runnable 的run 方法。而此时,
已经路由到UI 线程里,因此,我们可以毫无顾虑的来更新UI。

4) 几点小结
· Handler 的处理过程运行在创建Handler 的线程里
· 一个Looper 对应一个MessageQueue
· 一个线程对应一个Looper
· 一个Looper 可以对应多个Handler
· 不确定当前线程时,更新UI 时尽量调用post 方法
分享到:
评论

相关推荐

    Android线程结束——合理的结束你想结束的线程

    总结,结束Android线程时,关键在于优雅、安全地中断操作,而不是简单粗暴地停止。合理的线程管理可以提升用户体验,避免ANR,并保持应用程序的稳定运行。正确使用Thread、AsyncTask、Handler和Looper等工具,结合...

    浅谈android线程模型

    ### 浅谈Android线程模型:深入理解与实践 #### 引言 随着智能手机的普及和技术的不断进步,Google的Android操作系统成为了移动设备领域的重要力量。Android不仅为用户提供了丰富的功能,也为开发者提供了广阔的...

    Android多线程文件上传

    1. 使用AsyncTask:Android提供了一个内置的异步任务类AsyncTask,它可以轻松地在后台线程执行任务并在UI线程更新结果。不过,由于AsyncTask的限制(如线程池大小),对于大量并发任务,可能不是最佳选择。 2. ...

    Android开发中的多线程编程技术

    在Android应用开发中,多线程技术是必不可少的,它能帮助开发者实现高效的代码执行,提升用户体验,并确保应用程序的响应性。本资源包主要聚焦于Android平台上的多线程编程,包括理论概念、最佳实践以及实际应用案例...

    android 线程之间通过Handler发送消息

    首先,理解Android线程模型至关重要。Android应用的主要工作线程被称为UI线程或主线程,它负责处理用户界面的更新和事件响应。后台线程通常用于执行耗时任务,避免阻塞UI线程。为了在后台线程和主线程之间交换数据和...

    Android线程间通信的Message机制

    Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制Android线程间通信的Message机制

    android 线程间通讯

    在Android系统中,线程间通信(Inter-Thread Communication,简称ITC)是应用程序开发中的重要环节,尤其在处理耗时操作或者优化UI性能时显得至关重要。线程间通信允许不同线程之间交换数据和执行任务,以确保主线程...

    android 线程暂停/恢复/退出demo

    在Android开发中,多线程是必不可少的一部分,特别是在处理耗时任务时,如网络请求、数据库操作或大计算量的任务。...通过实践这个“android 线程暂停/恢复/退出demo”,开发者可以加深对Android线程管理的理解。

    从现实生活中理解android 线程消息机制

    在Android系统中,线程消息机制是一个核心概念,它确保了应用程序的高效运行和用户体验的流畅性。这个机制主要由三部分组成:Handler、Looper和Message Queue。下面我们将从现实生活中的例子来深入理解这个机制,并...

    android多线程管理

    在Android开发中,多线程管理是至关重要的技术,它涉及到应用的性能、用户体验以及资源的有效利用。Android系统默认在主线程(UI线程)执行所有的用户交互,如果在这个线程中执行耗时操作,会导致应用程序无响应...

    Android 中三种启用线程的方法总结

    首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。 而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。 ...

    Android多线程分段下载源码

    1. **线程管理**:创建一个线程池,根据用户指定的线程数来启动并管理下载线程。每个线程负责下载文件的一个部分。 2. **任务分配**:每个线程需要知道自己的起始和结束位置,以便正确地请求服务器上的数据块。这...

    Android 线程+View的使用

    在Android开发中,线程和View的交互是十分常见的需求,因为Android的UI操作必须在主线程中进行,而耗时的操作(如网络请求、大数据处理等)则应该放在子线程中。本实例主要探讨如何在子线程中更新View,通过两种方式...

    Delphi XE5例子中的一个Android线程使用的代码AnonymousThread.rar

    1. **匿名线程(AnonymousThread)**: 在Delphi中,线程可以是命名的或匿名的。在这个例子中,“AnonymousThread”指的是没有特定名称的线程。创建匿名线程是为了执行后台任务,不影响主线程的用户界面操作。 2. ...

    Android多线程操作

    在Android应用开发中,多线程是一个至关重要的概念,它涉及到如何在后台处理耗时任务,以避免阻塞主线程并提升用户体验。标题"Android多线程操作"和描述"Android多线程开发实例,对使用多线程的用户有一定的参考价值...

    android 单线程 多线程下载

    1. **单线程下载**: 在单线程下载中,所有的下载任务都在一个单独的工作线程中进行。这种做法简单易懂,但存在效率问题。因为网络请求是异步的,如果只有一个线程,当下载速度慢或者网络不稳定时,整个下载过程会...

    android多线程demo(很清晰很详细)

    本文将深入探讨Android多线程的相关知识点,基于“android多线程demo(很清晰很详细)”的描述,我们将围绕这个示例进行讲解。 1. **线程基础**: - **主线程**:Android应用的UI线程,负责处理用户交互和更新界面。...

    Android----线程实现图片移动

    1. **创建线程**: 可以使用`Thread`类直接创建一个新线程,或者使用更现代的`AsyncTask`,`Handler`/`Looper`,或者`Runnable`与`ExecutorService`。考虑到这是一个简单的任务,`Thread`或`Runnable`配合`Looper`...

    Android-android简单的链式线程切换工具类简单适用可用于学习线程相关知识

    本文将深入探讨由用户分享的"ThreadUtils"工具类,它为Android开发者提供了一种简单的链式线程切换方法,有助于理解和应用线程相关知识。 首先,让我们了解Android中的线程模型。主线程,也称为UI线程,负责处理与...

    android线程启动方法源代码

    本文将深入解析Android线程启动的方法,并通过源代码示例帮助初学者理解和掌握这一关键技能。 Android系统基于Java,因此其线程机制遵循Java的基本规则,但同时也有一些特定于Android平台的特性。在Android中,主要...

Global site tag (gtag.js) - Google Analytics