- 浏览: 158685 次
- 性别:
- 来自: 深圳
-
最新评论
-
dawei1980:
请问,解压密码是多少?
Android本地APP集成Mui框架 -
牧羊之人:
Android本地APP集成Mui框架 -
还有也许:
貌似懂了一点。如果onCreate方法中创建了一个db,然后在 ...
Android线程模式(handler,thread,looper) -
chenshijun0101:
header里面怎么更改他的样式呢?急求
android Preference相关样式修改 -
qlraishui:
good
Binder机制分析【三】-service绑定Binder

多线程与异步
Main Thread & UI Thread
当程序启动的时候Android会自动创建一个进程和一个线程,这个线程负责界面更新,收集系统事件和用户的操作事件等并分配给对应的组件,所以这个线程非常重要 被称为主线程,因为所的和UI有关的操作都是在这个线程当中进行的所以也被称作UI线程。所以说默认情况下主线程和UI线程指的是同一个线程。For instance, when the user touches a button on the screen, your app's UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.
Android的UI系统参考了很多SWT的设计模式。比如,UI线程机制,底层JNI实现 etc.
Android 的UI系统是非线程安全的,意思是说只有创建UI的线程(也就是主线程)才可以对UI进程操作。如果我们在其它线程中执行了一些操作,而这些操作的结果又需要通过UI展现给用户,必需把这更新UI的操作转移到到UI线程中执行。
很多Java起步的程序员对UI线程中的"消息循环"会感觉陌生。其实就是在线程内部有一个死循环一直监听系统事件(用户的操作等)并把任务分发给对应的组件(有兴趣的可以看看NDK附带的native-activity的一个sample,在c中的实现方式就是一个while(1)的死循环)。主线程通过Looper实现了消息的循环处理。
The ralationship between Handler,Message,MessageQueue and Looper?
如果一个线程里边有一个死循环,那么这个循环就会一直在死循环里边循环,并且这个线程不会过多的cpu资源,那么这个线程肯定的阻塞的。如果线程只是一直循环没有什么意义,实际情况通常需要线程根据不同的条件运行不同的方法。我们通常的作法可能会加一个switch开关,根据条件的不同去调用不同的方法。
线程间通信(最常见的就是,worker线程需要更新UI),这个时候实际是包含两个内容:一,数据的传递;二,方法的传递; Android中的Message用于数据传递,而Handler就是方法传递(其实是方法的执行者,Handler会把这个方法放到Handler所在的线程当中去执行);MessageQueue是Message的容器和Java中的Queue一样都是容器,只不过Message Queue是专门用于装载Message的容器。Looper则是一个线程中的死循环用于管理MessageQueue,它负责阻塞读取MessageQueue中的信息(如果MessageQueue中没有信息会一直在那里),挨个读取并把这个Message分发给对应的Handler去执行。
通过一个小例子+源码追踪下它们之间是怎么工作的,关系是什么样的
public class HandleMessageTrackActivity extends Activity { final static int SHOW_ALERT = 1025; Activity mActivity; TextView displayText; Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case SHOW_ALERT: showAlert((String) msg.obj); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mActivity = this; displayText = new TextView(this); setContentView(displayText); displayText.setText("Just ignore me"); new Thread() { @Override public void run() { String Greetings = "Greetings from another Thread"; mHandler.obtainMessage(SHOW_ALERT, Greetings) .sendToTarget(); } }.start(); } private void showAlert(String content) { AlertDialog.Builder builder = new Builder(mActivity); builder.setMessage(content); builder.create().show(); } }
首先看一下mHandler.obtainMessage(SHOW_ALERT, Greetings).sendToTarget();会执行什么。 通过查看Handler的源码发现执行了下边的代码。
public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); }
接着查看Message中的代码,
public static Message obtain(Handler h, int what, Object obj) { Message m = obtain(); m.target = h; m.what = what; m.obj = obj; return m; } /*** * Return a new Message instance from the global pool. Allows us to* avoid * allocating new objects in many cases. */ public static Message obtain() { synchronized (mPoolSync) { if (mPool != null) { Message m = mPool; mPool = m.next; m.next = null; return m; } } return new Message(); }
看到这里我们应该明白为什么Google建议我们使用obtainMessage而不是new一个Message.这也是符合了Android中的对象回收机制。
public void sendToTarget() { //targe就是一个Handler target.sendMessage(this); } //sendMessage()会调用下面的sendMessageAtTime()把Message加入MessagQueue; 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; } }
到此我们的Message对象被加入到了Handler所在线程(也就是主线程)中的MessageQueue这个存储和管理Message的容器当中。下一步就该由Looper接手一个一个的取出Message对象处理了。Looper最主要的方法就是loop()方法
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; } if (me.mLogging!= null) me.mLogging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg);//target of a msg is a Handler if (me.mLogging!= null) me.mLogging.println( " Finished to " + msg.target + " " + msg.callback);//msg.callback is a Runnable msg.recycle(); } } } } } } }
Looper会一直阻塞读取MessagQueue中的Message对象(Message msg = queue.next()),当读取到一个Message时就会调用msg.target.dispatchMessage(msg)把这个Message分发给对应的Handler去处理,等Handler把任务处理完了再接着读取下一个Message对象并处理。
/*** Handle system messages here.*/ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); // call the run method of the runnable object I guess } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } } }
最后回来了我们的handlerMessage(msg);这个方法中。如果是用的不是sendMessage是是Hadler.post(Runnable)会调用
private final void handleCallback(Message message) { message.callback.run();}这就是为什么在Handler中post的Runnable不会开启一个新的线程的原因。经过上面的追踪我们应该能明白不是所有 的线程都可以有Handler去执行handlerMessage或者处理Runnalbe的。其必要条件就是这个线程要有一个一直循环的Looper.Looper一直循环肯定要有一个方法可以退出循环。
public void quit() { Message msg = Message.obtain(); // NOTE: By enqueueing directly into the message queue, the // message is left with a null target. This is how we know it is // a quit message. mQueue.enqueueMessage(msg, 0);}
当我们调用msg.sendToTarget()的时候,我们的msg对象应付被压入MessageQueue的尾部。Looper在MessageQueue的另一端一个一个的读取信息并处理。根据msg的target属性把cpu分配给对应的Handler去执行任务,这时Handler会根据msg中的属性调用msg.handleMsg()或者msg.callback.run();当一个msg中的消息处理完返回之后Looper会把这个msg放入msgPool当中方便下次再重复利用。从而减少对象的创建。Looper再从MessageQueue中读取下一个信息,如此反复。。
理解了这些其实就不难想象ANR是如何实现的了。当用户执行操作(比如点击了一个按钮)系统会生成一个Message对象,把用户操作的信息写入Message对象,并把这个Message对象压入MessageQueue队列的尾部。系统过一段时间(一般是五秒)后会再来检查,刚刚放入的信息是不是已经被处理了,如果信息还在队列中就表明。处理前面信息的过程当中发生的阻塞,用户的操作没有及时得到响应。系统弹出ANR对话框。
作个总结:
因为UI线程需要保持一直运行的状态,所以要有一个循环保持这个线程不会死掉,但这个线程又必需阻塞,以减少cpu的消耗。android中的这个循环就是通过Looper实现的。有了这个 Looper,Looper就占据了整个线程,导致所有的方法想在些线程中运行就必需通过这个Looper,所以要有个方法可以进入这个Looper的内部。MessageQueue就担当了这个通道 的角色。Message担当了集合的角色。所有在UI线程中运行的方法都必需通过MessageQueue进入Looper内部,不管 是用户定义的方法还是系统事件包括onCreate(),onStop(),用户点击事件etc..
MessageQueue包含两个方法,next()和enquenceMessage(),一个用于读取message,一个用于写入message,它们的访问都是通过jni访问的C层,message也是存储在C层的。在next方法中,如果messagequeue中没有消息,则进入wait。在写入消息时,再进行唤醒操作
发表评论
-
判断图片是浅色还是深色
2020-03-04 13:23 815首先需要获取 WallpaperManager.FLAG_L ... -
如何将uri转成真实路径地址
2018-10-15 17:38 1239/** * 获取文件选择器选中的文 ... -
备用网址记录
2018-01-08 11:05 461各种开源下载 http://www.mvnjar.com/ ... -
android中touch事件,click事件,longclick事件分析
2016-08-03 15:51 1514针对屏幕上的一个View控件,Android如何区分应当触发o ... -
Android 快速开发系列 打造万能的ListView GridView 适配器
2016-06-27 17:21 688前往 http://blog.csdn.net/lmj6235 ... -
android中的Handler和AsyncTask如何防止内存泄露
2016-06-13 13:55 1655Handler泄露的关键点有两个: 1). 内部类 ... -
[转载]SharedPreferences 存储java对象,很实用
2016-04-14 16:36 1081public void putObject(String ke ... -
Android本地APP集成Mui框架
2016-01-26 14:41 31692.如何在安卓原生APP中 ... -
Android与设计模式浅谈
2015-04-27 10:42 1118Android作为新一代的操作系统,集合着Google ... -
从网页启动Activity
2015-03-24 11:28 1386正好Android SDK 给我们提供了解决方案,在网页中点击 ... -
[转]android shape的使用
2014-10-13 13:30 782shape用于设定形状,可以在selector,layout等 ... -
touch事件分发处理流程
2014-05-23 09:44 837Touch 事件发生时 Activity 的 dispatch ... -
修改标准GSensor相关,是重力感应游戏在平板都可以玩
2013-12-21 11:27 879为什么有些重力感应的游戏不能玩,有些可以玩,主要原因在于fra ... -
Android模拟按键
2013-10-14 14:27 2438如果想要实现类似iphone的悬浮框按钮,那就必须知道如何去模 ... -
android资源适配解析及资源适配优先级规则
2013-10-12 12:41 36951.sw的值是怎么计算得来 ... -
[转]隐藏虚拟按键(导航栏)的方法
2013-10-12 10:35 2913Controls for system UI visibili ... -
【转】解决Android与服务器交互大容量数据问题
2013-09-02 14:40 2085对于目前的状况来说, ... -
[转载]Android大图裁剪解决办法
2013-04-25 14:29 2168cropimage 可以调用手机自带的com.android ... -
反锯齿办法
2012-12-28 14:14 975在Android中,目前,我知道有两种出现锯齿的情况。 ① ... -
android线程的那些事
2012-11-17 15:36 2338有些时候Thread里面更新UI是可以成功的。 比如在Acti ...
相关推荐
【Android 线程间通信:Handler、Looper 和 MessageQueue 深度解析】 在 Android 应用开发中,为了保证界面的流畅性,我们通常需要将耗时操作放在非 UI 线程中执行,然后通过某种机制将结果传递回 UI 线程进行界面...
### Android之Looper、MessageQueue、Handler与消息循环详解 #### 一、概述 在Android开发过程中,消息处理机制是至关重要的部分,它涉及到应用程序如何管理、传递和响应各种事件。本篇文章将深入探讨Android中...
深入 Android Handler,MessageQueue 与 Looper 关系 Android 消息机制是 Android 程序设计中非常重要的一部分,其中 Handler、MessageQueue 和 Looper 是三个紧密相关的概念。Handler 是 Android 消息机制的上层...
当Handler的`sendMessage(Message)`方法被调用时,Message会被放入与Handler关联的MessageQueue,等待Looper取出并分发。 ```java // sendMessage方法 public final boolean sendMessage(Message msg) { return...
`Looper` 的典型工作模式是调用 `loop()` 方法进入无限循环,从而不断从 `MessageQueue` 中读取消息并传递给对应的 `Handler` 进行处理。 4. **MessageQueue (消息队列)**:`MessageQueue` 是一个 `Looper` 的成员...
在这个过程中,`Looper`会不断地调用`MessageQueue.next()`方法来获取下一个待处理的消息,并通过`Handler.dispatchMessage()`方法将消息传递给对应的`Handler`进行处理。 #### 三、MessageQueue详解 `Message...
7. **MessageQueue插队**:`MessageQueue.next()`方法允许开发者获取并立即处理下一个消息,跳过其他等待的消息,但这需要谨慎使用,因为它可能破坏消息的正常顺序。 8. **Message的target属性**:除了Handler外,...
- **Handler/Looper/Message Queue**:通过创建Handler对象,与主线程的Looper和Message Queue协同工作,实现异步消息处理。 - **AsyncTask**:简化了在后台线程执行任务并在UI线程更新结果的流程。 2. **Handler...
4. **Looper**:充当MessageQueue和Handler之间的桥梁角色,负责循环取出MessageQueue中的消息,并交给对应的Handler处理。 #### 四、消息处理流程 1. **创建Handler**:每个需要处理消息的线程都需要一个Handler...
Handler、Looper和MessageQueue是Android系统中用于实现线程间通信的关键组件,它们共同构成了Android的消息处理机制。这里我们将深入探讨这些概念,并通过一个仿写Handler机制的例子来理解其工作原理。 首先,我们...
- **Looper与Message Queue**:Looper是Message Queue的管理者,负责从Message Queue中取出消息并分发给相应的Handler进行处理。Looper通常在主线程中初始化,确保主线程能够持续不断地检查Message Queue并处理消息...
在实际开发中,Handler还有其他高级用法,如Looper、MessageQueue和Looper.prepare()等。Looper是主线程的消息循环器,MessageQueue则是存储待处理消息的队列。当我们调用`Looper.prepare()`时,会初始化Message...
本文将深入探讨Handler、Looper、Message和MessageQueue等核心概念,以及它们如何协同工作以实现生产者-消费者模型。 首先,Handler扮演着发送和接收消息的角色。在子线程中,开发者可以通过创建Handler实例来发送...
Handler、Looper和MessageQueue之间的关系关系 在理解Handler的工作原理前,需要了解三个关键组件:Handler、Looper和MessageQueue。它们共同构成了Android的消息传递机制。 1. **MessageQueue**:消息队列,用于...
Handler是Android系统中用于线程间通信的关键组件,它的内部实现原理涉及到...在编程实践中,深入理解Handler、Looper和MessageQueue之间的关系,以及它们如何协同工作,对于编写高效且稳定的Android应用至关重要。
,这个题目有点意思,对于很多人来说,可能对Thread和Handler很熟悉,主要涉及到Android的消息机制(Handler、Message、Looper、MessageQueue),详见《 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及...
本主题将深入探讨自定义Handler、Looper、MessageQueue和Message类,帮助开发者更好地理解Android的Handler机制。 首先,我们来了解一下`Handler`。`Handler`是Android中用于发送和处理消息的核心类。它允许开发者...
Android应用的运行基于消息驱动模型,这一模型的核心在于Looper、Handler和MessageQueue的协同工作。下面我们将深入理解这三个组件的作用及其交互。 1. **Message(消息)**: - Message是应用程序中传递信息的...
一个`Handler`对象通常与特定的`Looper`和`MessageQueue`关联,`Looper`循环地从`MessageQueue`中取出消息并分发给相应的`Handler`进行处理。这样,我们可以在工作线程中执行耗时任务,然后通过`Handler`将结果发送...