一篇明白Andorid中的Handler

什么是handler

handler是一套 Android 消息传递机制,这里的消息指的是message类,可以理解成handler是对message进行传递的一种机制。

handler的作用

在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理

相关概念

主线程:
又可以称作UI线程,当应用程序启动时,会自动开启主线程
子线程:
又可以称为工作线程,开发自己创建的线程,可以用来执行耗时操作
Message:
可用于线程间通信,时线程间通讯的一种数据单元,存储了需要操作的通信信息

Message Quenue
消息队列,一种先进先出的数据结果,存储着Handler发送的消息
handler
message的处理者,发送和接收message
添加Message到Message Quene,处理Looper分派过来的Message

Looper:
循环器,循环去除消息队列(Message Quenue)的消息(message);将取出的Message发送给对应的Handler

注意点
每个线程中只能拥有1个looper ,1个Looper可以绑定多个线程的Handler。

handler使用

方式1:使用 Handler.sendMessage()
步骤1:
在主线程中创建handler

 class mHandler extends Handler {

        // 通过复写handlerMessage() 从而确定更新UI的操作
        @Override
        public void handleMessage(Message msg) {
         ...// 需执行的UI操作
            
        }
    }
    private Handler mhandler = new mHandler();

步骤2:创建Message

Message msg = Message.obtain();//实例化消息对象,obtain采用的为对象池,防止多次创建对象
msg.what = 1; // 消息标识
msg.obj = "AA"; // 消息内容存放

步骤3:
在子线程中通过Handler发送消息到消息队列中

 mHandler.sendMessage(msg);

步骤4:开启工作线程

方式2:使用Handler.post()

// 步骤1:在主线程中创建Handler实例
    private Handler mhandler = new mHandler();

    // 步骤2:在工作线程中 发送消息到消息队列中 & 指定操作UI内容
    mHandler.post(new Runnable() {
            @Override
            public void run() {
                ... // 需执行的UI操作 
            }

    });

    // 步骤3:开启工作线程(同时启动了Handler)
    // 多线程可采用AsyncTask、继承Thread类、实现Runnable

handler 工作原理

在这里插入图片描述
注意点:
1个线程(Thread)只能绑定 1个循环器(Looper),但可以有多个处理者(Handler)
1个循环器(Looper) 可绑定多个处理者(Handler)
1个处理者(Handler) 只能绑定1个1个循环器(Looper)

handler部分源码分析

暂时学识浅薄,后续补上

handler内存泄漏

垃圾回收机制:
Java虚拟机中使用可达性分析的算法来决定对象是否可以被回收。即通过GCRoot对象为起始点,向下搜索走过的路径(引用链),如果发现某个对象或者对象组为不可达状态,则将其进行回收。
产生内存泄漏的整体原因
内存泄漏指的就是有些对象(短周期对象)没有用了,但是却被其他有用的类(长周期对象)所引用,从而导致无用对象占据了内存空间,形成内存泄漏。
handler产生内存泄漏的复现
handler做一个延时操作,没等message被处理,activity进行销毁操作。
发现强制GC也不能回到初始值,说明产生了内存泄漏
handler内存泄漏的原因
1.内部类默认持有了外部类的引用,所以handler持有它的外部activity类
2.根据持有路径分析:
主线程 —> threadlocal —> Looper —> MessageQueue —> Message —> Handler —> Activity
这种情况下程序还存活的时候,主线程不会销毁,自然不会GC activity对象,导致内存泄漏
注意:这种情况是message还没处理完,activity就销毁了
解决方法
1.说到底,就是activity被销毁,已经是没用了,但是还是被Handler持有,导致不能被释放,导致内存泄漏
所以一种想法就是让handler不持有activity

 // 设置为:静态内部类
    private static class FHandler extends Handler{

        // 定义 弱引用实例
        private WeakReference<Activity> reference;

        // 在构造方法中传入需持有的Activity实例
        public FHandler(Activity activity) {
            // 如果想使用Activity实例,则用WeakReference弱引用持有Activity实例
            reference = new WeakReference<Activity>(activity); }
        @Override
        public void handleMessage(Message msg) {
 
        }
    }

2.当外部类结束生命周期时,清空Handler内消息队列

@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        // 外部类Activity生命周期结束时,同时清空消息队列 & 结束Handler生命周期
    }

HandlerThread 实现 子线程和主线程直接双向通信,具体用法


使用步骤:
//1、创建HandlerThread对象,即创建了一个新的线程,参数为线程名,仅仅是标记线程用的
     HandlerThread mHandlerThread = new HandlerThread("mHandlerThread");
//2、开启线程,第一步创建了一个新的线程,此处开启线程。
    mHandlerThread.start();
//3、创建Handler,并重写handleMessage()方法
    //new Handler(mHandlerThread.getLooper()),即把该Handler绑定到mHandlerThread线程的Looper,
    //进而绑定到了线程mHandlerThread
     Handler mHandlerInHandlerThread = new Handler(mHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
 	        //对信息的相关处理操作               
                //在子线程mHandlerThread中运行   
                super.handleMessage(msg);
            }
        };
//4、创建消息并发送消息
    //在主线程中
    Message msg = Message.obtain();
    //主线程向子线程mHandlerThread发送消息通信
    mHandlerInHandlerThread.sendMessage(msg);
//5、结束线程。之前开启线程,当工作结束不再使用该线程时,应该结束该线程
    //即停止了线程的消息循环
    mHandlerThread.quit();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值