美文网首页android内存管理
android内存泄漏快速解决——内部类改为静态类

android内存泄漏快速解决——内部类改为静态类

作者: 朱_c713 | 来源:发表于2020-01-15 15:20 被阅读0次

在内存泄漏的解决中,内部类(案例为:匿名内部类)改成静态类绝对是一大杀器。比这曾经在一个项目中用这种方法,解决了百分之70的泄漏。解决方案简单粗暴

1)就是将匿名内部类改写为静态类,并添加弱引用

问题代码:(我使用阿里热修复的时候的代码):

SophixManager.getInstance().setPatchLoadStatusStub(new PatchLoadStatusListener() {

            @Override

            public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
              //todo something
              }
})

使用LeakCanranry,直接报泄漏,泄漏日志显示“是PatchLoadStatusListener 持有acitivity 引用”
这个案例是在首页做的,只要一按下返回键,必现泄漏。

处理方法就是改写为:

private static class MyPatchLoadStatusListener  implements PatchLoadStatusListener {

private WeakReferenceweakReference;

    public MyPatchLoadStatusListener(HomeActivity homeActivity) {

weakReference =new WeakReference<>(homeActivity);

    }

@Override

    public void onLoad(int i, int code, String s, int i2) {

}

}

调用的地方修改为:

SophixManager.getInstance().setPatchLoadStatusStub(new MyPatchLoadStatusListener(this));

修正后,leakcananry 不再报错。开发中养成良好的习惯,坚决不写有泄漏的代码

2)内部类改成外部类,并添加弱引用

开发一个倒计时splash页面,之后进入应用。在进入的时候,发现leakCananry报泄漏。日志如下:

内部类持有外部类的引用

重点看哪里呢,重点看紫色实线和虚线的交叉处,如果只有虚线,直接从虚线底端看起


观察如上部分

这里表明了,是匿名内部类TimeTask持有引用了ActivityAdvertising ,导致我们出现了泄漏:
找到代码:

public class ActivityAdvertising extends MyActivity {
.....
  ScheduledExecutorService newScheduledThreadPool = Executors
            .newScheduledThreadPool(1);
    private int time;
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(() -> {
                time--;
                if (countdownProgressView != null) {
                    touch_ok.setClickable(false);
                    countdownProgressView.setText(time + "s");
                }
                if (time <= 0) {
                    if (countdownProgressView != null) {
                        countdownProgressView.setText("進入");
                        touch_ok.setClickable(true);
                    }
                }
            });
        }
    };
}
....

一看代码,高危呀,匿名内部类。 处理成外部类问题解决:


public class Ttimetask extends TimerTask {
    public WeakReference<ActivityAdvertising> weakReference;
    public Ttimetask(ActivityAdvertising activityAdvertising){
       weakReference =new WeakReference<ActivityAdvertising>(activityAdvertising);
    }
    @Override
    public void run() {
        weakReference.get().runTimeTask();
    }
}

调用的地方:


class ActivityAdvertising : MyActivity() {
 
    internal var newScheduledThreadPool = Executors
        .newScheduledThreadPool(1)
    private var time: Int = 0

    var timerTask=Ttimetask(getActivity())
    fun runTimeTask(){
        runOnUiThread {
            time--
            if (countdownProgressView != null) {
                touch_ok!!.isClickable = false
                countdownProgressView!!.text = time.toString() + "s"
            }
            if (time <= 0) {
                if (countdownProgressView != null) {
                    countdownProgressView!!.text = "進入"
                    touch_ok!!.isClickable = true
                }
            }
        }
    }
   
    override fun initView() {
        timerTask.run()

    }

    fun cancelTimer() {
        if (timerTask != null) {
            timerTask.cancel()
        }
    }


    override fun initData() {       
        time = 5
        newScheduledThreadPool.scheduleAtFixedRate(timerTask, 0, 1000, TimeUnit.MILLISECONDS)     

    } 

    override fun onDestroy() {
        super.onDestroy()
        cancelTimer()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)       
    }

}

一个timeTask泄漏就解决掉了:网上很多人说是需要添加 TimeTask的取消方法,kotlin版本下我的代码实测没有通过,我是通过外部类的方法解决掉的:


微信图片_20200304143258.png

再次点击,leakCanary下,测试了一大波,还是只有Audiodmanager的泄漏,timeTask泄漏顺利解决。

Android内存泄漏解决(总)

相关文章

  • android内存泄漏快速解决——内部类改为静态类

    在内存泄漏的解决中,内部类(案例为:匿名内部类)改成静态类绝对是一大杀器。比这曾经在一个项目中用这种方法,解决了百...

  • Android内存泄漏之集合类

    Android内存泄漏基本可以分为以下四大类:1、集合类泄漏2、单例/静态变量造成的内存泄漏3、匿名内部类/非静态...

  • Android性能-内存泄漏

    泄漏原因: 单例造成的内存泄漏 非静态内部类(匿名类等)创建静态实例造成的内存泄漏 Handler/Thread/...

  • 关于Android的内存泄漏

    关于Android的内存泄漏 知识补充: <1.静态内部类和外部类生命周期区别: 生命周期:静态内部类随着外部类的...

  • Android常见内存泄漏

    内存泄漏场景: 静态变量引用非静态内部类/匿名类实例。子线程相关的非静态内部类/匿名内部类引用。Handler导致...

  • Android内存分析:profiler + MemoryAna

    一些内存泄漏的场景: 1 非静态内部类的静态实例2 多线程相关的匿名内部类/非静态内部类3 Handle内存泄漏4...

  • Android内存优化——常见内存泄露及优化方案

    内存泄漏情况分类 1、单例模式导致内存泄漏 2、静态变量导致内存泄漏 3、非静态内部类导致的内存泄漏 4、未取消注...

  • 如何减少Android中存在的内存泄露

    Java细节:1. 非静态内部类会持有外部类的隐式引用。容易导致内存泄露,解决方法:改为静态内部类。2. 这样会有...

  • Android常见内存泄漏汇总

    目录:一、内存泄漏介绍二、常见内存泄漏场景1.单例导致内存泄露2.静态变量导致内存泄漏3.非静态内部类导致内存泄露...

  • 关于静态内部类

    静态内部类与非静态内部类的区别 非静态内部类会隐式持有外部类的引用,可能引起内存泄漏。 静态内部类只能调用外部类的...

网友评论

    本文标题:android内存泄漏快速解决——内部类改为静态类

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