美文网首页
[安卓开发日记] 内存泄漏

[安卓开发日记] 内存泄漏

作者: chopperhl | 来源:发表于2020-04-02 16:53 被阅读0次

一、JAVA的四种引用类型

1.强引用

Object obj = new Object();
String str = "Hello";

这类通常的实例化对象

2.弱引用

WeakReference 当JVM进行垃圾回收时无论内存是否充足,都会回收被弱引用关联的对象。可用于解决内存泄漏

3.软引用

SoftReference 只有当JVM内存不足时才会回收软引用关联的对象

4.虚引用

PhantomReference 不影响对象的被垃圾回收的时机

 ReferenceQueue<String> queue = new ReferenceQueue<String>();
 PhantomReference<String> pr = new PhantomReference<String>("Hello" queue);

虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。

二、Handler导致的内存泄漏

非静态的Handler内部类,默认会持有外部的Activity引用。

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        handler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
            }
        };
        Message message = handler.obtainMessage(1);
        message.obj = "Hello";
        handler.sendMessageDelayed(message, 40000);
    }

Handler#sendMessageDelayed 方法,会调用Handler.mQueen.enqueueMessage(Message msg, long when)
将Message 加入 MesssageQueen ,并设置设置message.target = this(Handler对象)
上诉流程会形成 如下依赖链


Message -> MessageQueen -> Handler -> Activity

MesageQueen->MainLooper(和application生命周期一致)

Message 和 MessageQueen 的依赖 Message 被发送时才会解除
Activity退出后,在Delay时间到达之前,无论发生多少次GC,根据可达性分析,Activity的内存都不应该被释放。

解决方案
  • 切断Message到Queen 到引用链,即在Activity销毁时调用 handler.removeMessages(1)
  • 将Handler到Activity的引用变为弱应用,即改用静态的Handler子类,传入WeakReference的Activity应用:
    public static class DetailHandler extends Handler {
        private WeakReference<DetailActivity> contextWeakReference;

        public DetailHandler(DetailActivity context) {
            this.contextWeakReference = new WeakReference<>(context);
        }

        public DetailActivity getContextWeakReference() {
            return contextWeakReference.get();
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    }

3.静态的实例持有非静态的类(短周期的对象)

public class AppManager {
    private static AppManager INSTANCE;
    private Context context;

    private AppManager(Context context) {
        this.context =  context;
    }

    public static AppManager getInstance(Context context) {
        return new AppManager(context);
    }

    public void test(){

    }
}

INSTANCE 的生命周期和整个App一致,如果getInstance 传入的Context 为Activty,则Activty会被AppManager一直持有,导致Activity在gc时不能被释放。

解决方案

这里传入ApplicationContext这样的长周期对象即可。
其他类型的引用可以根据实际情况,在适当的时机置空即可。

相关文章

  • [安卓开发日记] 内存泄漏

    一、JAVA的四种引用类型 1.强引用 这类通常的实例化对象 2.弱引用 WeakReference 当JVM进...

  • (转载自diycode)2017 Android 面试题分享整理

    Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析及解决 An...

  • android 内存性能

    handle引起的内存泄漏 强引用资源引起的内存泄漏 线程导致的内存泄漏 系统学习安卓内存泄露 large hea...

  • 2016.8

    8.4 Android 开发常见错误解决方案(不断更新中)安卓面试题 5 – 关于内存泄漏 Android 开发人...

  • 安卓开发 内存泄漏问题

    1.及时释放不用的资源,如bitmap、media等 2.正常使用hanlder时,hanlder会持有外部类的潜...

  • android学习资料

    第一部分: Android(安卓) Android基础知识 Android内存泄漏总结 Handler内存泄漏分析...

  • 安卓内存泄漏

    Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏...

  • Android知识体系总结

    第一部分:Android(安卓)Android基础知识Android内存泄漏总结Handler内存泄漏分析及解决H...

  • 安卓日记Handler的内存泄漏

    Handler大家都在用,用来线程的通信,实现异步间的信息传递handler有个小坑 不优化的话 会引起内存泄漏要...

  • 安卓内存泄漏测试

    一、测试环境安装(如果已安装可以省略此步骤) 1.adb命令环境安装 sdk文件放置在PC盘符如下图 系统环境变量...

网友评论

      本文标题:[安卓开发日记] 内存泄漏

      本文链接:https://www.haomeiwen.com/subject/mzbxphtx.html