【Android+Kotlin】WeakReference与Handler小结

扉:查阅大量文章,大多是讲WeakReference原理的(弱引用,内存不够时GC回收),但没有说明项目中具体的使用。因为不确定啥时候会被回收,单纯用在变量上不太安全(我要用结果被回收了岂不是报空指针)

1. 目前了解到WeakReference比较适合用于处理Handler的内存泄漏(实际上会强持有activity的引用,而强引用处理不当容易引起内存泄漏)

一:解决Handler

1. 参考文章:WeakReference在Handler中的应用

2.还原步骤

1. 代码块

  1. Mainac,这个都很熟悉了,先定义一个handler(在30版本Handler被弃用了。。。不是吧),再用匿名类处理回调。下面oncreate方法进行发送消息。
class MainActivity : AppCompatActivity() {

    var handler: Handler = @SuppressLint("HandlerLeak")
    object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
        }
    }

    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
    }
}

2. 问题分析

  1. 原博主说:段代码在handler对象创建的时候却会报警告:This Handler class should be static or leaks might occur。意思是:Handler类应该为static类型,否则可能会造成内存泄漏。(这个报错我在AsyncTask中见过)
  2. 由于android的特殊机制:当一个android主线程被创建的时候,同时会有一个Looper对象被创建,而这个Looper对象会实现一个MessageQueue(消息队列),当我们创建一个handler对象时,而handler的作用就是放入和取出消息从这个消息队列中,每当我们通过handler将一个msg放入消息队列时,这个msg就会持有一个handler对象的引用。因此当Activity被结束后,这个msg在被取出来之前,这msg会继续存活但是这个msg持有handler的引用,而handler在Activity中创建,会持有Activity的引用,因而当Activity结束后,Activity对象并不能够被gc回收,因而出现内存泄漏。
  3. 但是为什么为static类型就会解决这个问题呢?因为在java中所有非静态的对象都会持有当前类的强引用,而静态对象则只会持有当前类的弱引用。声明为静态后,handler将会持有一个Activity的弱引用,而弱引用会很容易被gc回收,这样就能解决Activity结束后,gc却无法回收的情况。
  4. 解决方案
    1)将hanlder对象声明为静态的对象。
    2)使用静态内部类,通过WeakReference实现对Activity的弱引用。具体实现看以下代码
    a. 使用静态内部类和WeakReference
    3) 当外部类结束生命周期时,清空Handler内消息队列

class MainActivity : AppCompatActivity() {
    

    var handler = MyHandler(this)
    
    //kotlin 静态内部类   加了inner为非静态
    class MyHandler(activity: MainActivity?) : Handler() {
        var mactivity: WeakReference< MainActivity> = WeakReference<MainActivity>(activity)
        override fun handleMessage(msg: Message) {
            if (mactivity.get()==null)
                return
            super.handleMessage(msg)
            when (msg.what) {
                100 -> {
                }
                else -> {
                }
            }
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
//为保证消息都能被执行,这种方法不推荐使用
@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        // 外部类Activity生命周期结束时,同时清空消息队列 & 结束Handler生命周期
    }

二:额外原理文档参考声明

  1. WeakReference 学习和使用
  2. 强引用(New)、软引用(SoftReference )、弱引用(WeakReference )、虚引用(PhantomReference)
  3. 不需要使用WeakReference来避免内存泄露
  4. GC机制
  5. Java篇 - 四种引用(Reference)实战
  6. Java WeakReference的理解与使用
  7. 基础-WeakReference
  8. WeakReference是什么,什么时候要使用WeakReference
  9. 弱引用和软引用WeakReference,SoftReference,最简讲解,以及一个应用场景
    10.为什么Android官方废弃SoftRefrerence软引用和WeakReference弱引用,而拥抱LruCache?
  10. Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
  11. 彻底解析Android缓存机制——LruCache
  12. LruCache——解决OOM的利器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值