android耗时任务_handler

handler机制的5个角色

在上一篇android处理耗时任务_ANR中简单的介绍了一个handler的用法,现在我们来看看他的基本原理。

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

Message:消息,携带要传送的信息和任务,是handler机制的载体。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

Looper和MessageQueue一一对应,创建一个Looper的同时会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,

即Handler里会引用当前线程里的特定Looper和MessageQueue。这样说来,多个Handler都可以共享同一Looper和MessageQueue了。

当然,这些Handler也就运行在同一个线程里。本人专门画了下面的图,我想这个图已经能够简洁明了的说明他们的关系了。

一个简单的实例

		class LooperThread extends Thread {
                               public Handler mHandler;
                               public void run() {
                                               Looper.prepare();
						//Handler不带参数的默认构造函数:new Handler(),实际上是通过Looper.myLooper()来获取当前线程中的消息循环
                                               mHandler = new Handler() {
                                                               public void handleMessage(Message msg) {
                                                                              // process incoming messages here
                                                               }
                                               };
                                               Looper.loop();
                               }

                }

默认情况下一个线程是不存在消息循环Looper的,需要调用Looper.prepare()来给线程创建一个Looper,同时会创建一个MessageQueue,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。Looper.loop()其实就是开启了一个死循环,不停的从MessageQueue中抽取Message并分配。所以写在Looper.loop()之后的代码不会被立即执行,当调用后mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

值得一提的是,Android中很多的线程间的通信都和Handler有关:

Activity.runOnUiThread(Runnable)

View.post(Runnable)

View.postDelayed(Runnable, long)

上面三个其实都和handler.post(Runnable)有关。

Activity.runOnUiThread(Runnable)

如果当前线程是UI线程,那么该Runnable会立即执行,如果当前的线程不是UI线程则调用UI线程handler的post()方法将其放入UI线程的消息队列中。

View.post(Runnable)

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。

时间: 2024-12-17 09:53:26

android耗时任务_handler的相关文章

android耗时任务_HandlerThread

HandlerThread 在上一篇android耗时任务_handler中介绍了handler的运作机制,并且介绍了一个普通线程中产生looper并使用handler机制通信的简单例子.我们知道在普通线程中是没有looper的,也就不好在普通线程空间中使用handler机制,如果每次都像上一篇的例子那样做的话就会略显麻烦.其实Android已经封装了一个拥有自己looper的线程HandlerThread,它的实现和上一篇中给出的例子基本一,只是更加专业一点.下面是此类的详细代码. publi

android耗时任务_IntentService

如果你看到上一篇android耗时任务_HandlerThread中所提到的BackService类了的话,那么你肯定有一个冲动,就是把它封装起来方便使用. 别急,Android SDK早就已经为我们提供了和那个BackService基本相同的类--IntentService.因为IntentService和BackService基本相同,所以源码我就不贴了. 先来看一下一个简单的例子: public class AsyncService extends IntentService { publ

Android耗时操作

No subscribers registered for event class com.test.MessageEvent import de.greenrobot.event.EventBus; 不是 org.....那个包 内存中要先有订阅者,然后发送者才能把信息发送到他那. A->B ,Activity A发送给B, 则B这个Activity要先有. 可以配置B为app的启动页面,然后跳转到A,则此时内存中AB都有(先有B,再有A),然后A发送消息给B,最终B的吐司能在A页面上看到,在

android耗时任务_AsyncTask

AsyncTask是sdk封装好的一个轻量级的用于执行异步任务的工具类,所谓轻量级,就是说对于一两个线程就能完成的任务,AsyncTask能够非常快速方便的实现,但是对于像ListView每个item都需要进行刷新的异步任务,AsyncTask就没有那么容易去做了,而且做出来的效果也不好. 下面来看一下这个类的基本结构 public class MyTask extends AsyncTask<Params, Progress, Result>{ @Override protected voi

使用Dnsmasq作为dhcp,解决IOS连接路由器慢

android手机第一次连接路由器WiFI速度很快,而苹果手机连接速度很慢,原因主要有两个:1.IOS系统WiFI存在Bug:2.dhcp服务器分配IP地址时间过长. 通过dnsmasq日志发现,IOS第一次连接路由器WiFI耗时原因: 1.读取机子中ip地址缓存,耗时1s(android不会): 2.发送REQUEST报文,报文里的IP是机子上次连接WiFi的分配的IP地址,如果不是同一个网段的路由器,dnsmasq直接发送NACK报文(设置dnsmasq配置文件,如果不设置,耗时2s): 3

Android测试读写sd卡文件与写sd卡文件耗时

测试从sd卡读1k大小的文件,再写1k大小的文件,由于处理耗时很短,所以循环500次,查看耗时:测试写1k大小的文件,直接在内存构造一个1k的buffer,将这个buffer直接写到文件,同样循环500次,查看耗时. 思路:首先读写文件,建立文件输入输出流,然后将读取的数据直接写入文件,打印时间戳,查看耗时:只写文件,新建一个1k的buffer,然后用文件输出流写入文件,打印时间戳,查看耗时. 直接上代码: 1 package com.example.ghimtim.myapplication;

Android(Java)控制GPIO的方法及耗时分析

前面两篇分别介绍了通过脚本和C代码读写/sys/class/gpio以控制GPIO.实际项目调试时经常还需要在Java代码里控制GPIO,其实现与C代码类似,唯一不同是Android权限.本文重点介绍Android6.0权限的配置并对在Java层控制GPIO的耗时做简单分析. 以高通平台为例,权限配置主要修改HLOS/device/qcom/sepolicy/common目录下的file.te.file_contexts和system_app.te三个文件. file.te修改如下, # GPI

Android Studio学习随笔-模拟耗时操作(sleep)

在这里我申明一点,因为我是挂着VPN去YOUTOBE看的尚学堂的高明鑫老师讲的Android基础学习视频,有些东西他没有讲,而我也没办法,只能等两个星期后学校请老师来的时候进行询问,当然我也会将一些问题发布在博客里,希望有一些粗腿可以让我抱一下 在此次随笔中,我将讲一下用sleep进行的耗时操作,由于高老师在视频中也是一掠而过,我也只能讲一点点,先附上代码 1 button.setOnClickListener(new View.OnClickListener() { 2 @Override 3

Android开发中的耗时操作总结

Android开发中的耗时操作总结 在Android软件开发过程中,经常遇到耗时操作.为了使手机app运行流畅,耗时操作需要在新的一个线程中完成.那么,Android手机应用开发中,耗时操作有哪些呢?下面来总结一下. 下载文件操作 网络连接操作(尤其是网络不好的时候) 音频格式转换操作 文件操作 比较大的数据的初始化操作 sleep函数等 注: 具体的功能还得根据业务需求来完成.