Handler的简单实用和介绍

来源:互联网 发布:2017剑灵人男捏脸数据 编辑:程序博客网 时间:2024/06/03 15:15

前奏:

在Android开发中,我们常常会使用单独的线程来完成某些操作,比如用一个线程来完成从网络上下载图片然后显示到一个ImageView中,但是我们往往会遇到以下的经典的错误提示:

 Only the original thread that created a view hierarchy can touch its views.错误信息  //只有原始的创建他的线程才能去更新ui

也就出现了在多线程操作时,Android必须保证以下两点:

  • 1、不要阻塞UI线程
  • 2、不要在UI线程之外访问Android UI工具包(禁止非UI线程更新UI)

那么这个时候我们就可以通过一个轻量级的Handler来解决我们的这个问题了哈。怎么解决呢,这个地方我们先上一段解决方案,具体的介绍在说。(这里有个隐患,先留着,如果你已经知道了,那么很厉害哈,我也是刚知道怎么回事呢

 @Override    public void onClick(View v) {        new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    try {                        //这里我们只是简单的模拟一下下载3000秒后通知刷新ui                        Thread.sleep(3000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    break;                }                mHandler.sendEmptyMessage(100);                //这里我建议大家去看下官网handler的介绍,发送消息有很多方法呢,延迟,直接发送。在这里只是简单的使用了一种发送空消息                }            }.start();

通过以上的简单的代码逻辑,我们就可以完成我们在UI线程中更新UI了。是不是挺方便的。
好了接下来,就来看下什么是Handler和和Handler有关的几个类吧。

Handler实现机制:

**Android启动程序的时候会在UI线程创建一个MessageQueue。**

我们来看下他们几个的图形相关信息:

在来看下他们几个的关系;

  • 1、message 消息对象,内部使用链表结果实现一个消息池,用于重复利用,避免大量的创建消息,造成内存浪费
  • 2、handler 消息处理着,通过该对象把消息存入消息队列中,并且最后通过handlerMessage方法来处理消息
  • 3、MessageQueue 消息队列,用于存储Message消息对象的数据结构,先进先出
  • 4、Looper 消息轮寻器,用于循环检查消息队列中是否有消息,如果有消息就取出来,然后传递给handlerMessage方法中等待处理

想必这个时候,大家应该对于handler机制有了一定的了解,不过建议大家可以去看下源码,把他们的流程走一下,应该会有不错的认识。这里就不带着走源码了。

背景颜色引发的内存泄露问题:

想必大家在刚开始看的时候,已经发下了我所说的,这一段代码有点问题吧,我刚开始使用也不知道,想着是故意这样的呢,也就没太注意,有的时候看其他人写的blog,有介绍的,当时也没有太注意,只是知道是内存泄露(今天关于内存泄露不过多说(我也不是很明白的哈)望谅解),但是昨天同学问我的时候,我也只是说了句内存泄露,但是并不能很好的解释,给他找了资料,让他自己研究去了,有幸今天我有点空,就来研究一下。我们先来看下图:

这个地方是不是颜色和其他地方不一样呢,我们把鼠标放到handlerMessage上面按下ctrl + f1(win) ,出现以下解释:

大概的意思就是handler定义一个内部类的时候,对于这个外部类来说,造成了引用,来阻止外部类被回收,如果handler使用了Looper或者MessageQueue在子线程而非main线程,那么久没有问题,但是如果是在main线程中,你就要做出如下的改变了,声明为静态的,然后在外部类中实例化WeakReference 的外部类,然后在实例化这个处理程序的时候,传入这个引用对象。

这个时候我们就要了解一java的四种引用了,在这推荐一篇
http://blog.csdn.net/coding_or_coded/article/details/6603549
那么既然这样提示了,我们就来修改吧。

Handler内存泄露的问题:

内部类会持有外部类的引用,也就是handler会获取到当前类的引用,内部类的对象要依赖于外部类的额对象,如果要退出activity,那么这个对象就要销毁,但是handler还在工作,获取到引用,那么这个时候就不能退出(我的handler还在工作(必须等待handler处理完成))。

  • 1、定义一个内部类的时候,会默认拥有外部类对象的引用,所以建议使用内部类的时候,最好定义为一个
  • 2、需要用到弱引用 强引用》》软引用》》弱引用
    好了,我们看下最后的修改的代码,为了直观看到解决问题,我这里截图来看下,是不是没有暗黄色背景了哈。(代码风格统一,处女座的热爱(我不是哈))

    我们来看下怎么使用吧。
//这个时候我们就可以使用handler里面的各种暴漏的方法了哈 //使用handler延迟执行一个runnable(10分钟)        mMyHandler.postDelayed(new Runnable() {            @Override            public void run() {                Log.d("Main2Activity", "handler");            }        }, 1000 * 60 * 10);

好了,今天就到这了哈,有问题可以讨论哈。

0 0
原创粉丝点击