服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android handler 详解(面试必问)

Android handler 详解(面试必问)

2021-06-09 16:09hyyweb Android

这篇文章主要介绍了Android handler的相关资料,涉及到handler相关知识,需要的朋友可以参考下

handler在android中被称为“消息处理者”,在多线程中比较常用。

handler为android提供了一种异步消息处理机制,当向消息队列中发送消息 (sendmessage)后就立即返回,而从消息队列中读取消息时会阻塞,其中从消息队列中读取消息时会执行handler中的public void handlemessage(message msg) 方法,因此在创建handler时应该使用匿名内部类重写该方法,在该方法中写上读取到消息后的操作,使用handler的 obtainmessage() 来获得消息对象。

  handler与线程的关系:

  使用handler的post方法将runnable对象放到handler的线程队列中后,该runnable的执行其实并未单独开启线程,而是仍然在当前activity线程中执行的,handler只是调用了runnable对象的run方法。

  bundle是什么:

  bundle是一个特殊的map,它是传递信息的工具,它的键只能是string类型,而且值也只能是常见的基本数据类型。

handler内部实现原理

Android handler 详解(面试必问)

handler实现机制:

1,message对象,表示要传递的一个消息,内部使用链表数据结构实现一个消息池,用于重复利用,
避免大量创建消息对象,造成内存浪费
2,messagequeue对象,存放消息对象的消息队列,先进先出原则
3,looper对象负责管理当前线程的消息队列
4,handler对象负责把消息push到消息队列中,以及接收looper从消息队列中取出的消息

handler的内存泄露问题(activity已经退出,而handler没有退出,这样就可能导致内存泄露)

1,定义一个内部类时,会默认拥有外部类对象的引用,所以建议使用内部类时,最好定义一个静态内部类
2,引用的强弱:强引用→软引用→弱引用

下面用获取网络图片代码说明一下handler基本使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.example.uri;
import java.io.ioexception;
import java.io.inputstream;
import java.lang.ref.weakreference;
import java.net.malformedurlexception;
import java.net.url;
import android.net.uri;
import android.os.bundle;
import android.os.handler;
import android.os.message;
import android.app.activity;
import android.content.context;
import android.content.intent;
import android.graphics.bitmap;
import android.graphics.bitmapfactory;
import android.view.menu;
import android.view.view;
import android.widget.imageview;
/**
*
* 访问网络的操作,必须放在工作线程中完成
*
*/
public class mainactivity extends activity {
private static final int loadsuccess=0x1;
private static imageview iv;
private final myhandler handler=new myhandler(this);
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
iv=(imageview) findviewbyid(r.id.imageview1);
}
private static class myhandler extends handler{
private final weakreference<mainactivity> weakreference;
public myhandler(mainactivity mainactivity){
weakreference=new weakreference<mainactivity>(mainactivity);
}
public void handlemessage(message msg) {
mainactivity mainactivity=weakreference.get();
if(mainactivity!=null){
switch (msg.what) {
case loadsuccess:
mainactivity.iv.setimagebitmap((bitmap) msg.obj);
break;
}
}
}
}
public void geturl(view v){
/*intent intent = new intent(intent.action_view, uri.parse("http://www.baidu.com"));
startactivity(intent); */
new thread(new runnable() {
@override
public void run() {
try {
url url=new url("http://img2.3lian.com/img2007/10/28/123.jpg");
inputstream in=url.openstream();
bitmap bitmap=bitmapfactory.decodestream(in);
message message= handler.obtainmessage(loadsuccess, bitmap);
handler.sendmessage(message);
} catch (malformedurlexception e) {
// todo 自动生成的 catch 块
e.printstacktrace();
} catch (ioexception e) {
// todo 自动生成的 catch 块
e.printstacktrace();
}
}
}).start();
}
}

如何让handler执行runnable时打开新的线程:

  1、首先生成一个handlerthread对象,实现了使用looper来处理消息队列的功能,这个类由android应用程序框架提供
  handlerthread handlerthread = new handlerthread("handler_thread");

  2、在使用handlerthread的getlooper()方法之前,必须先调用该类的start();
  handlerthread。start();

  3、根据这个handlerthread对象得到其中的looper对象。

  4、创建自定义的继承于handler类的子类,其中实现一个参数为looper对象的构造方法,方法内容调用父类的构造函数即可。

  5、使用第三步得到的looper对象创建自定义的handler子类的对象,再将消息(message)发送到该handler的消息队列中,handler复写的handlemessage()将会执行来处理消息队列中的消息。

以上给大家详细介绍了android handler 相关知识,希望对大家有所帮助!

延伸 · 阅读

精彩推荐