导航:首页 > 使用方法 > androidhandler使用方法

androidhandler使用方法

发布时间:2023-01-06 03:55:07

A. Android Handler机制 怎么

Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用线程也会堵塞。每个Handler对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue)。如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
在主线程中,可以直接使用new Handler()创建Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样创建Handler则会报错,因为Android系统默认情况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。这种情况下,需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上;或者通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。
Handler发送的消息都会加入到Looper的MessageQueue中。一说Handler包含两个队列:线程队列和消息队列;使用Handler.post()可以将线程对象加入到线程队列中;使用Handler.sendMessage()可以将消息对象加入到消息队列中。通过源码分析证实,Handler只有一个消息队列,即MessageQueue。通过post()传进去的线程对象将会被封装成消息对象后传入MessageQueue。
使用post()将线程对象放到消息队列中后,当Looper轮询到该线程执行时,实际上并不会单独开启一个新线程,而仍然在当前Looper绑定的线程中执行,Handler只是调用了该线程对象的run()而已。如,在子线程中定义了更新UI的指令,若直接开启将该线程执行,则会报错;而通过post()将其加入到主线程的Looper中并执行,就可以实现UI的更新。
使用sendMessage()将消息对象加入到消息队列后,当Looper轮询到该消息时,就会调用Handler的handleMessage()来对其进行处理。再以更新UI为例,使用这种方法的话,就先将主线程的Looper绑定在Handler对象上,重载handleMessage()来处理UI更新,然后向其发送消息就可以了。

B. Android面试必问handler机制浅析

Handler是Android中的异步消息处理机制。当发送一个消息之后,这个消息是进入一个消息队列(MessageQueue),在消息队列中通过Looper去循环的获取队列中的消息,然后将消息分派给对应的处理者进行处理。

Message:存储需要处理操作的信息

MessageQueue:先进先出,存储handler发送过来的消息

Looper:循环器,它是消息队列和handler的通信媒介,1:循环的取出消息队列中的消息;2:将取出的消息发送给对应的处理者

Handler:主线程和子线程的通信媒介,1:添加消息到消息队列; 2:处理循环器分派过来的消息

在handler机制中,Looper.loop方法会不断循环获取Message, 其中的消息的获取是通过调用MessageQueue的next()方法获取的,而该方法会调用nativePollOnce()方法 ,这是一个native方法。底层的实现涉及到Linux pipe/epoll机制,nativePollOnce()被阻塞时,主线程会释放CPU资源,进入休眠状态. 直到下个消息到达或者有事务发生,会通过pipe管道写端写入数据来唤醒looper工作。

Android6.0及以前的版本使用管道与epoll来完成Looper的休眠与唤醒的

Android6.0及以后的版本使用eventfd与epoll来完成Looper的休眠与唤醒的

如果不处理的话,会阻塞线程,处理方案是调用Looper的quit()(清空所有的延迟和非延迟的消息)和quitSafely()(只清空延迟消息); 这个方法会调用MessageQueue的quit()方法,清空所有的Message,并调用nativeWake()方法唤醒之前被阻塞的nativePollOnce(),使得方法next()方法中的for循环继续执行,接下来发现Message为null后就会结束循环,Looper结束。如此便可以释放内存和线程

同进程线程间内存共享,通过handler通信,消息的内容是不需要从一个线程拷贝到另一个线程,因为两个线程间可使用的内存是同一个区域。(注意:线程私有区域ThreadLocal)

管道的作用就是当一个线程准备好Message,并放入消息池,这时需要通知了一个线程B去处理这个消息。线程A向管道的写端写入数据,管道有数据便会唤醒线程B去处理消息。管道的作用是用于通知另一个线程的,这便是最核心的作用。

从内存角度,通信过程中binder涉及到一次内存拷贝,handler机制中的Message根本不需要拷贝,本身就是在同一片内存。

从CPU角度,为了Binder通信底层驱动还需要创建一个binder线程池,每次通信涉及binder线程的创建和内存的分配等比较浪费CPU资源

原因:handler发送的消息在当前handler的消息队列中,如果此时activity被finish掉了,那么消息队列的消息依旧由handler进行处理,若此时handler申明为内存类(非静态内部类),内部类持有外部类的实例引用,这样在GC垃圾回收时发现Activity还有其他引用存在,因而就不会去回首这个Activity,进而导致Activity泄漏。

方法:使用静态内部类,并且使用WeakReference包裹外部类的对象。首先静态内部类不持有外部类的引用,使用静态的handler不会导致activity的泄漏,handler定义static的同时,还要用WeakReference包裹外部类的对象。

C. Android Handler使用

在日常开发中,都避免不了进行网络请求,并更新View,由于Android中主线程不可以进行耗时操作,所以我们的网络请求只能放在子线程中,又由于在子线程中不能更新UI,所以我们就需要使用Handler切换到主线程并更新UI。

在介绍Handler使用之前,我们先了解以下两个问题。

1、为什么主线程不能进行耗时操作?
因为如果在主线程进行耗时操作,容易出现ANR,Application Not Responding,即应用无响应,当在一定的时间内,app无法响应时就会出现ANR,并弹出一个 对话框提示应用无响应,所以我们应该避免在主线程中进行耗时操作,当我们应用出现ANR时,会在
/data/anr/目录中生成traces.txt,我们可以通过这个文件查找错误信息。

2、为什么子线程中不能更新UI?
这是因为在子线程中更新UI不是线程安全的,在Android源码ViewRootImpl的checkThread方法中也对UI做了验证。

基于这两个问题,我们可以使用Handler来解决,接下来介绍Handler的基本使用。

首先创建Handler

接下来发送消息。

这个时候在handlerMessage方法中即可收到消息,获取Message中的数据,并更新UI了。是不是很简单。

D. Android中的Handler机制

Handler常用于Android中线程间通信
消息处理流程有一张图可以参考下

这里有几个重要的关键点(按我自己理解翻译的一下)
1.Message:消息
2.MessageQueue:消息队列
3.Handler:消息处理器,负责消息的收发,可以存在多个
4.Looper:循环消息分发器

通信嘛,要先有传递的信息Message

MessageQueue,消息同时发又处理不完又需要保持同步,于是有了消息队列,让消息按顺序处理

Looper,消息分发器,在其loop()后会循环消息队列去取消息进行分发处理,如果没有则会阻塞

最后是Handler,负责消息的收发处理,sendMessage发送消息,重写handleMessage方法即可处理收到的消息(这里主线程直接获取了looper)如果是子线程则需要先对Looper就行初始化

介绍完功能来顺一下流程
首先主线程中ActivityThread中main方法创建了Looper

这里进入Looper

当我们需要传递消息时
通过获取对应线程Looper来初始化Handler,

初始化一个消息,Message.obtain()来获得而不是new一个Message,因为Message内部有一个消息池子,消息收到处理后,内部信息清除就可以重复使用,避免资源浪费。

然后插入到Handler所在的消息队列

然后Loop发现有新消息,派发到对应的Handler来处理消息dispatchMessage

Handler.dispatchMessage,先判断是否有callback(即Runnable),如果有走handleCallback,否则执行handleMessage

简单总计一下:
线程间通信每个线程都需要初始化Looper和消息队列,Loop不停向消息队列读取消息,通过不同线程的Handler来发送信息,如A线程有1,2两个Hander,B线程有3,4两个Hander,A线程调用3,4来发送信息,B线程即可收到 A线程发来的信息

阅读全文

与androidhandler使用方法相关的资料

热点内容
实训课程的教学方法是什么 浏览:519
苯甲醇乙醚鉴别方法 浏览:76
苹果手机微信视频声音小解决方法 浏览:694
控制箱的连接方法 浏览:69
用什么简单的方法可以去痘 浏览:783
快速去除甲醛的小方法你知道几个 浏览:798
自行车架尺寸测量方法 浏览:118
石磨子的制作方法视频 浏览:146
行善修心的正确方法 浏览:400
薯仔炖鸡汤的正确方法和步骤 浏览:272
北京电流检测方法 浏览:481
手机u盘保护方法 浏览:113
数字搭配有哪些方法 浏览:666
约一场球的正确方法 浏览:187
在家中洗衣服的方法如何 浏览:293
28天锻炼腹肌最快的方法 浏览:203
简单练翘臀方法视频 浏览:760
心理诊断评估常用的方法有哪些 浏览:844
什么方法能让手机不黑屏 浏览:723
电脑开机慢的处理方法视频 浏览:724