Android 性能优化最佳实践,写给程序员的Flutter详细教程

本文详细介绍了Android应用性能优化,特别是内存泄漏的原因和解决策略,包括集合类、单例模式、匿名内部类/非静态内部类及资源未关闭等问题。此外,还探讨了应用启动过程中的冷启动、热启动和温启动,提出启动速度优化的建议,并分享了避免启动时密集初始化、I/O操作和网络操作的方法。文章最后提及包体优化的重要性,并分享了作者的个人经验和学习资源。
摘要由CSDN通过智能技术生成

内存泄漏指的是那些程序不再使用的对象无法被GC识别,这样就导致这个对象一直留在内存当中,占用了没来就不多的内存空间。

内存泄漏是一个缓慢积累的过程,一点一点的给你,温水煮青蛙一般,我们往往很难直观的看到,只能最后内存不够用了,程序奔溃了,才知道里面有大量的泄漏,但是到底是那些地方?估计是狼烟遍地,千疮百孔,都不知道如何下手。怎么办?最让人难受的是内存泄漏情况那么多,记不住,理解也不容易,关键是老会忘记。怎么办呢?老这么下去也不是事,总不能面试的时候突击,做项目的时候不知所措吧。所以一定要记住了解GC原理,这样才可以更准确的理解内存泄漏的场景和原因。不懂GC原理的可以先看一下这个JVM初探:内存分配、GC原理与垃圾收集器

本来GC的诞生是为了让java程序员更加轻松(这一点隔壁C++痛苦的一匹),java虚拟机会自动帮助我们回收那些不再需要的内存空间。通过引用计数法,可达性分析法等等方法,确认该对象是否没有引用,是否可以被回收。

有人会说真么强悍的功能看起来无懈可击啊,对,理论上可以达到消除内存泄漏,但是很多人不按常理出牌啊,往往很多时候,有的对象还保持着引用,但逻辑上已经不会再用到。就是这一类对象,游走于GC法律的边缘,我没用了,但是你又不知道我没用了,就是这么赖着不走,空耗内存。

因为有内存泄漏,所以内存被占用越来越多,那么GC会更容易被触发,GC会越来越频发,但是当GC的时候所有的线程都是暂停状态的,需要处理的对象数量越多耗时越长,所以这也会造成卡顿。

19956127-6ee96f2eea77bd64.png

那么什么情况下会出现这样的对象呢? 基本可以分为以下四大类: 1、集合类泄漏 2、单例/静态变量造成的内存泄漏 3、匿名内部类/非静态内部类 4、资源未关闭造成的内存泄漏

1、集合类泄漏

集合类添加元素后,仍引用着集合元素对象,导致该集合中的元素对象无法被回收,从而导致内存泄露。

举个栗子:

static List mList = new ArrayList<>();

for (int i = 0; i < 100; i++) {

Object obj = new Object();

mList.add(obj);

obj = null;

}

当mList没用的时候,我们如果不做处理的话,这就是典型的占着茅坑不拉屎,mList内部持有者众多集合元素的对象,不泄露天理难容啊。解决这个问题也超级简单。把mList清理掉,然后把它的引用也给释放掉。

mList.clear();

mList = null;

2、单例/静态变量造成的内存泄漏

单例模式具有其 静态特性,它的生命周期 等于应用程序的生命周期,正是因为这一点,往往很容易造成内存泄漏。 先来一个小栗子:

public class SingleInstance {

private static SingleInstance mInstance;

private Context mContext;

private SingleInstance(Context context){

this.mContext = context;

}

public static SingleInstance newInstance(Context context){

if(mInstance == null){

mInstance = new SingleInstance(context);

}

return sInstance;

}

}

当我们在Activity里面使用这个的时候,把我们Acitivty的context传进去,那么,这个单例就持有这个Activity的引用,当这个Activity没有用了,需要销毁的时候,因为这个单例还持有Activity的引用,所以无法GC回收,所以就出现了内存泄漏,也就是生命周期长的持有了生命周期短的引用,造成了内存泄漏。

所以我们要做的就是生命周期长的和生命周期长的玩,短的和短的玩。就好比你去商场,本来就是传个话的,话说完就要走了,突然保安过来非要拉着你的手,说要和你天长地久。只要商场在一天,他就要陪你一天。天呢?太可怕了。叔叔我们不约,我有我的小伙伴,我还要上学呢,你赶紧找你的保洁阿姨去吧。你在商场的生命周期本来可能就是1分钟,而保安的生命周期那是要和商场开关门一致的,所以不同生命周期的最好别一起玩的好。

解决方案也很简单:

public class SingleInstance {

private static SingleInstance mInstance;

private Context mContext;

private SingleInstance(Context context){

this.mContext = context.getApplicationContext();

}

public static SingleInstance newInstance(Context context){

if(mInstance == null){

mInstance = new SingleInstance(context);

}

return sInstance;

}

}

还有一个常用的地方就是Toast。你应该知道和谁玩了吧。

3、匿名内部类/非静态内部类

这里有一张宝图:

19956127-6e1dfdedc4275cdb.png

非静态内部类他会持有他外部类的引用,从图我们可以看到非静态内部类的生命周期可能比外部类更长,这就是二楼的情况一致了,如果非静态内部类的周明周期长于外部类,在加上自动持有外部类的强引用,

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值