Android 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内部实现原理
handler实现机制:
1,Message对象,表示要传递的一个消息,内部使用链表数据结构实现一个消息池,用于重复利用,
避免大量创建消息对象,造成内存浪费
2,MessageQueue对象,存放消息对象的消息队列,先进先出原则
3,Looper对象负责管理当前线程的消息队列
4,handler对象负责把消息push到消息队列中,以及接收Looper从消息队列中取出的消息
handler的内存泄露问题(activity已经退出,而handler没有退出,这样就可能导致内存泄露)
1,定义一个内部类时,会默认拥有外部类对象的引用,所以建议使用内部类时,最好定义一个静态内部类
2,引用的强弱:强引用→软引用→弱引用
下面用获取网络图片代码说明一下handler基本使用
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 相关知识,希望对大家有所帮助!
相关文章
Android UI设计系列之自定义DrawView组件实现数字签名效果(5)
这篇文章主要介绍了Android UI设计系列之自定义DrawView组件实现数字签名效果,具有一定的实用性和参考价值,感兴趣的小伙伴们可以参考一下2016-06-06Android Studio中快捷键实现try catch等功能包含代码块的实现方法
这篇文章主要介绍了 Android Studio中快捷键实现try catch等功能包含代码块的实现方法的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下2017-09-09
最新评论