【Android 性能优化知识点】

本文详细介绍了Android应用中的内存管理问题,包括内存抖动、OOM异常、内存泄漏的常见情况和解决方法,如单例模式引发的内存泄漏、Handler和WebView导致的内存泄漏,以及如何使用Glide避免内存泄漏。此外,还提到了分析内存泄漏的工具leakcanary和内存溢出的概念。
摘要由CSDN通过智能技术生成

Android 性能优化知识点

内存抖动

OOM

已经分配的内存+准备分配的内存 >= 内存的总大小,就会出现OOM

java.long.OutOfMemoryError:申请内存时,没有足够的内存空间可配分,就会报此异常

可能会出现OOM的情况:
Java堆内存溢出
无足够连续的内存空间
FD(文件)数量超出限制:最大限制1024
线程数量超出限制:最大限制1024
虚拟内存不足

内存泄漏

指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早会被占光

常见的内存泄漏如下:
单例造成的内存泄漏

//单例模式
单例模式在我们项目中经常会用到,比如,我们项目中使用ActivityManager单例,获取这个单例需要传入context对象。代码如下:
public class ActivityManager {
private static final String TAG = "ActivityManager";
 
    private Context context;
 
    private static ActivityManager instance;
 
    private ActivityManager(Context context) {
        this.context = context;
    }
 
    public static ActivityManager getInstance(Context context) {
        if (instance == null) {
            instance = new ActivityManager(context);
        }
        return instance;
    }
}

上面代码,在构造方法里传入context,如果不加注意,很容易因为生命周期的长短而引起内存泄漏。注意请在这里传入Application的context而不是Activity的context,因为如果传入的是Activity的context,当Activity退出时,此context并不会被回收,因为单例对象持有该context的引用,从而引起内存泄漏。如果传入的是Application的context,便不会引发内存泄漏,因为context的生命周期和Application一样长,所以正确的单例写法如下:

public class ActivityManager {
private static final String TAG = "ActivityManager";
 
    private Context context;
 
    private static ActivityManager instance;
 
    private ActivityManager(Context context) {
        this.context = context.getApplicationContext();
    }
 
    public static ActivityManager getInstance(Context context) {
        if (instance == null) {
            instance = new ActivityManager(context);
        }
        return instance;
    }
}

非静态内部类创建静态实例造成的内存泄漏
非静态内部类(包括匿名内部类)默认就会持有外部类的引用,当非静态内部类对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露。

public class TestLeakActivity extends Activity {
 
    private static TestResource mResource = null;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_leak);
        if (mResource == null){
            mResource = new TestResource();
        }
    }
 
    private class TestResource{
 
    }
}

解决方案
可以将非静态内部类改成静态内部类

private static class TestResource{
 
}

Handler造成的内存泄漏
往期有讲到,链接如下:
Handler面试知识点

线程造成的内存泄漏
也是把内部类改成静态内部类就解决了

WebView造成的内存泄漏
解决方案:
单独放在一个进程去使用,Activity销毁的时候直接在onDestory()直接android.os.Process.killProcess(android.os.Process.myPid) 销毁进程

资源对象未关闭导致
对于资源若在 Activity 销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏。
如广播、文件、Bitmap、数据库、EventBus等使用

Glide 内存泄漏的原因
Glide内存泄漏的主要原因是未正确释放加载的图片资源。当我们使用Glide加载图片时,它会将图片缓存再内存中,以便下次快速加载。然而,当我们不再需要这些图片时,如果没有正确释放,就会导致内存泄漏。

下面是一个使用Glide加载图片的示例代码:

Glide.with(context)
    .load(imageUrl)
    .into(imageView);

在这个示例中吗,我们使用Glide.with(context)开始一个Glide请求,并使用.load(imageUrl)加载图片。最后,使用`.into(imageView)将图片显示再ImageView中。
然而,这段代码存在一个潜在的内存泄漏问题。当Activity或Fragment销毁时,如果Glide请求还未完成,就会导致内存泄漏。

解决方案
为了避免Glide内存泄漏,我峨嵋你选用哟在合适的时机取消Glide请求。一般来说,我们可以在Activity或Fragment的生命周期方法取消Glide请求。
下面是一个示例代码,在Activity的onStop()方法中取消Glide请求:

protected void onStop() {
    super.onStop();
    Glide.with(context).pauseRequests();
}

@Override
protected void onStart() {
    super.onStart();
    Glide.with(context).resumeRequests();
}

在这个示例中,我们在onStop()方法中调用Glide.with(context).pauseRequests(),这样可以暂停Glide请求。而在onStart(),方法中调用Glide.with(context).resumeRequests(),这样可以恢复Glide请求

分析内存泄漏的工具
leakcanary

内存溢出

指程序在申请内存时,没有足够的内存空间共其使用,出现out of memory。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红桃三呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值