Android:用Handler实现异步处理功能

Android——Handler详解 1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes 阅读详情

一.一个问题

有这样一个问题值得我们思考,若把一些类似于下载的功能(既耗时且不一定有结果)写在Activity(主线程)里,会导致Activity阻塞,长时间无响应,直至页面假死(如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭")。因此,我们需要把这些耗时的操作放在单独的子线程中操作。这就是Handler的使命。Handler提供异步处理的功能,发送和接收不是同时的(Activity的主线程和线程队列里的线程是不同的线程,并行进行,互不影响)。

二.Handler简介

Handler 为Android操作系统中的线程通信工具,它主要由两个作用:(1)安排消息或Runnable 在某个主线程中某个地方执行(2)安排一个动作在另外的线程中执行。每个Handler对象维护两个队列(FIFO),消息队列和Runnable队列,都是有Android操作系统提供的。Handler可以通过这两个队列来分别:

  1. 发送、接受、处理消息–消息队列;
  2. 启动、结束、休眠线程–Runnable队列;

Handler的使用方法大体分为3个步骤:1.创建Handler对象。2.创建Runnable和消息。3.调用post以及sendMessage方法将Runnable和消息添加到队列。

三.Runnable队列

1.java中的线程

在java中,线程的创建有两种方法:继承Thread类和实现Runnable接口。而这最重要的都是要复写run方法来实现线程的功能。当线程的时间片到了,开始运行时,就执行run()函数,执行完毕,就进入死亡状态。

举个创建线程的例子:

Runnable r=new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("thread");
handler.postDelayed(thread, 3000);
}
};

2.关于Runnable队列

(1)原理

Android的线程异步处理机制:Handler对象维护一个线程队列,有新的Runnable送来(post())的时候,把它放在队尾,而处理Runnable的时候,从队头取出Runnable执行。当向队列发送一个Runnable后,立即就返回,并不理会Runnable是否被执行,执行是否成功等。而具体的执行则是当排队排到该Runnable后系统拿来执行的。这就好比邮局的例子。寄信者将信写好后放入邮筒就回家了,他并不知道邮件何时被邮局分发,何时寄到,对方怎样读取这些事。这样,就实现了Android的异步处理机制。

(2)具体操作

向队列添加线程:

handler.post(Runnable );将Runnable直接添加入队列

handler.postDelayed(Runnable, long)延迟一定时间后,将Runnable添加入队列

handler.postAtTime(Runnable,long)定时将Runnable添加入队列

终止线程:

handler.removeCallbacks(thread);将Runnable从Runnable队列中取出

四.消息队列
1.消息对象

(1)Message对象

Message对象携带数据,通常它用arg1,arg2来传递消息,当然它还可以有obj参数,可以携带Bundle数据。它的特点是系统性能消耗非常少。

初始化: Message msg=handler.obtainMessage();

(2)Bundle对象

Bundle是Android提供的类,可以把它看做是特殊的Map,即键值对的包。而它特殊在键和值都必须要是基本数据类型或是基本数据类型的数组(Map的键值要求都是对象),特别的,键要求都是String类型。用Message来携带Bundle数据:

放入:msg.setData(Bundle bundle);

取出:msg.getData();

2.关于消息队列

(1)原理

Android的消息异步处理机制:Handler对象维护一个消息队列,有新的消息送来(sendMessage())的时候,把它放在队尾,之后排队到处理该消息的时候,由主线程的Handler对象处理(handleMessage())。整个过程也是异步的,和Runnable队列的原理相同。

(2)具体操作:

向队列添加Runnable:

handler.sendMessage(Message);将消息发送到消息队列

msg.sendToTarget();同上

handler.sendMessageDelayed(Message,long);延迟一定时间后,将消息发送到消息队列

handler.sendMessageAtTime(Message,long)定时将消息发送到消息队列

msg.sendToTarget();

处理消息:

消息的具体处理过程,需要在new Handler对象时使用匿名内部类重写Handler的handleMessage(Message msg)方法,如下:

Handler handler=new Handler(){

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
。。。。。。

。。。。。。
}
};

五.Handler的两个作用

1.安排消息或Runnable 在某个主线程中某个地方执行

代码示例:
public class HandlerTestActivity extends Activity {
private Button start;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.handlertest);
start=(Button) findViewById(R.id.start);
start.setOnClickListener(new startListener());

System.out.println("Activity Thread:"+Thread.currentThread().getId());
}
Handler handler=new Handler();
Runnable thread=new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("HandlerThread:"+Thread.currentThread().getId());

}
};
class startListener implements OnClickListener{

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
handler.post(thread);

}

}

这个小程序中,首先程序启动,进入onCreate(),打印出当前线程(即主线程)的ID,之后点击按钮start,会将线程thread添加到线程队列,执行线程thread,thread的作用就是打印出当前线程的ID。在这个程序中,我们可以看到通过Handler我们可以实现安排Runnable 在某个主线程中某个地方执行,即作用(1)。

不过这里有个小小的陷阱,你发现了吗?这个程序看上去似乎实现了Handler的异步机制, handler.post(thread)似乎实现了新启线程的作用,不过通过执行我们发现,两个线程的ID相同!也就是说,实际上thread还是原来的主线程,由此可见,handler.post()方法并未真正新建线程,只是在原线程上执行而已,我们并未实现异步机制。

2.安排一个动作在另外的线程中执行。

(1)java中标准的创建线程的方法

第一步:

Runnable r=new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("thread");
handler.postDelayed(thread, 3000);
}
};

第二步:

Thread t=new Thread (r);

第三步:

t.start();

若把上面示例程序中的handler.post(thread);语句改成以上形式,通过打印我们可以看到,两个ID是不同的,新的线程启动了!

(2)关于Looper

Looper类用来为线程开启一个消息循环,作用是可以循环的从消息队列读取消息,所以Looper实际上就是消息队列+消息循环的封装。每个线程只能对应一个Looper,除主线程外,Android中的线程默认是没有开启Looper的。

通过Handler与Looper交互,Handler可以看做是Looper的接口,用来向指定的Looper发送消息以及定义处理方法。默认情况下Handler会与其所在线程的Looper绑定,即:

Handler handler=new Handler();等价于Handler handler=new Handler(Looper.myLooper());

Looper有两个主要方法:

Looper.prepare();启用Looper
Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

(3)Handler异步机制的实现

Handler是通过HandlerThread 使得子线程与主线程分属不同线程的。实际上,HandlerThread 是一个特殊的线程,它是一个封装好Looper的线程,

代码示例:

//创建一个名叫handler_hread的HandlerThread 对象
HandlerThread handlerThread=new HandlerThread("handler_hread");

//开启handlerThread,在使用handlerThread.getLooper()之前必须先调用start方法,否则取出的是空
handlerThread.start();

//将handler绑定在handlerThread的Looper上,即这个handler是运行在handlerThread线程中的
myHandler handler=new myHandler(handlerThread.getLooper());

class myHandler extends Handler{
public myHandler(){}
public myHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("Activity Thread:"+Thread.currentThread().getId());
}
}

这样,就实现了handler的异步处理机制,在调用handler.post()方法,通过打印线程ID可以得知,子线程与主线程是分属不同线程的。

TLF35584 窗口看门狗_理论篇 1)看门狗的结果(有效或无效触发)由相关的看门狗故障计数器独立监控。2)窗口看门狗的状态是WWO,它可能有“有效WWD触发”或“无效WWD触发”值。 阅读详情

相关推荐

【保姆级教程】YOLOv8_Pose多目标+关键点检测:训练自己的数据集

【保姆级教程】YOLOv8_Pose多目标+关键点检测:训练自己的数据集

m0_51579041的博客 1万+

子线程和主线程创建使用Handler不同处的源码分析

子线程的Handler 在使用handler时,会有在子线程创建handler的场景,那我们从Looper.java的源码中摘抄下面一段创建Hander的代码段: class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare...

c++ 中的符号-> 937

步进电机驱动.zip_STM32F103 电机_步进电机_步进电机驱动_步进驱动_电机驱动

使用STM32F103系列单片机,简便的步进电机驱动代码

Android多线程----异步消息处理机制之Handler详解

​【声明】  欢迎转载,但请保留文章原始出处→_→  生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4003922.html 联系方式:smyhvae@163.com    【正文】 虽然是国庆佳节,但也不能停止学习的脚步,我选择在教研室为祖国母亲默默地庆生。 关于Android...

weixin_33858249的博客 246

单线程模型中Message、Handler、MessageQueue、Looper之间的关系

Handler简介: 一个Handler允许你发送和处理Message和Runable对象,这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时,它就和创建它的线程绑定在一起了。这里,线程我们也可以理解为线程的MessageQueue。从这一点上来看,Handler把Message和Runa

疯狂小强 1589

Android(6)——Handler,异步任务

文章目录Android1 Handler1.1 概念1.2 Handler使用1.3 Handler 存在的问题1.4 Handler实践的三种效果2 异步任务2.1 AsyncTask2.2 网络下载demo Android 安卓开发者指南:https://developer.android.google.cn/guide 1 Handler 1.1 概念 1.Handler:消息分发对象,进行发送和处理消息,并且其Runable对象和一个线程的MessageQueue关联。 2.为什么要使用Handle

weixin_45044097的博客 837

android主线程handler,Android:Handler实现异步处理功能

一.一个问题有这样一个问题值得我们思考,若把一些类似于下载的功能(既耗时且不一定有结果)写在Activity(主线程)里,会导致Activity阻塞,长时间无响应,直至页面假死(如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭")。因此,我们需要把这些耗时的操作放在单独的子线程中操作。这就是Handler的使命。Handler提供异步处理功能,发送和接收不是同时的(...

weixin_39986178的博客 1000

AndroidHandler的简单理解和使用

简单来说,Handler就是用来传递消息的。 Handler可以当成子线程与主线程的消息传送的纽带。在安卓开发中,在子线程中无法刷新UI,是因为UI在子线程中刷新的话,是不安全的,就比如多个线程刷新UI,会造成UI更新冲突,这样是不安全的。 所以,Handler的作用就来了,子线程可以通过Handler来将UI更新操作切换到主线程中执行。 下面来操作一番: public class Ma...

宇某的博客 3万+

Handler机制

一些基础: handler主要用于在子线程中经行耗时操作避免阻塞UI线程再把消息发送到UI线程再经行处理handler机制中海包括了Looper,MessageQueue,ThreadLocal等。 Looper: handler一般的写法为: private Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(@NonNull Mes

Z2LYYYY的博客 1010

android中的handler的作用

最近想做个android的知识总结,把近2-3年来的android开发知识写写,分享给大家,也好让自己更深刻的理解android开发 android中的handler是一个很总要的知识,可以说android开发基本上避免不了handlerhandler的作用基本上可以概括为Android提供了一个异步的消息回调机制Handler,  它负责发送消息和处理线程消息队列中的消息及run

TonyJiang08的专栏 952

Android——Handler一篇就看懂

Android handler的详细讲解

未来源起的博客 9562

Android Handler的作用与用法

1.什么是handler? HandlerAndroid SDK来处理异步消息的核心类。 子线程与主线程通过Handler来进行通信。子线程可以通过Handler来通知主线程进行UI更新。 HandlerAndroid中引入的一种让开发者参与处理线程中消息循环的机制。每个Hanlder都关联了一个线程,每个线程内部都维护了一个消息队列MessageQueue,这样Handler实际上也就关...

天道酬勤的博客 1708

Android Handler使用介绍

Android 中的 Handler 是用来和线程通信的重要工具。它主要用于在后台线程中执行任务,并将结果传递回主线程以更新用户界面。

小旭的专栏 3581
上一篇: java中的修饰符static与静态方法及final的用法
下一篇: android 操作命令
奔跑的乌龟
博客等级 码龄15年 3粉丝 6原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值