欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android内存管理优化技巧

程序员文章站 2022-05-16 20:25:21
...

1.使用service的风险

当应用程序使用service执行后台操作时,一定要保证只用执行操作时才让service运行,操作完成时,service应当停止运行,为防止内存泄露,谷歌官方推荐使用IntentService。

2.当界面不可见的时候,释放内存

到用户打开另一个app时,上一个app已经处于不可见状态,我们应到把与界面有关的资源进行释放,只需要在Activity中,重写onTrimMemory()方法,然后在这个方法

中见监听TRIM_MEMORY_UI_HIDDEN这个级别,一旦触发之后可以进行一些操作:

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_UI_HIDDEN){
            //TODO Somethings
        }
    }


3.当内存紧张时释放内存

onTrimMemory()方法[整个程序不可见时,触发]方法有很多回调类型的函数,我们可以根据回调中传入的API级别,去处理资源:

TRIM_MEMORY_BACKGROUND 表示程序正常运行,不会被杀掉,但内存有点低,系统可能已经根据LruCache规则去杀进程

TRIM_MEMORY_MODERATE 表示程序运行正常,内存已经很低了,我们应该释放一些不必要的内存,否则会影响程序性能

TRIM_MEMORY_RUNNING_CRITICAL 表示程序运行正常,但系统已经开始根据lruCache规则杀掉大部分缓存进程,我们应当去释放不必要的资源

4.避免在Bitmap上浪费内存

这个前面说过,不懂的可以去看看前面博客的Bitmap加载大图优化和LruCache和DiskLruCache双缓存机制

5.使用优化过的数据集合

Android API中提供了一些优化过的数据集合工具类:SparseArray、SparseBooleanArray、LongSparseArray。可以让程序更加高效

举个例子,普通hashMap以整型为key存放数据:

这里共存放个5组数据,以整型为键值:

HashMap<Integer,String> map = new HashMap<>();

map.put(1,"value");

map.put(2,"value");

map.put(3,"value");

map.put(4,"value");

map.put(5,"value");

上面的HashMap在内存中开辟的空间是这样的:可以看出它存放数据时,开辟了63个空间只用了5个,绝大部分都浪费掉了

Android内存管理优化技巧

会造成内存的浪费

接下来看一下优化过的SparseArray,可以看到,他是根据使用到的数据个数进行开辟空间一共只用18个,大大节省内存开支

Android内存管理优化技巧

优化过的集合

SparseArray<String>  //已将key作为整形

SparseArray<String>  array = new SparseArray<>();

array.put(1,"value");

array.put(2,"value");

array.put(3,"value");

array.put(4,"value");

array.put(5,"value");



6.了解内存的开支状况

1>使用枚举通常会比使用静态常量要消耗两倍以上内存

2>任何一个Java类,包括内部类、匿名类都要占用500字节的内存空间

3>任何一个类的实例都要消耗12-16字节的内存开支,频繁new对象也会影响性能

4>使用HashMap时,即使只设置了一个基本数据类型的键,e.g  int,但也会按照对象的大小来分配内存,大概是32字节,因此,像上面一样

5>多用优化过的数据集合

7.反抽象编程概念

面向对象的编程,会编写很多额外的代码,即使这些代码执行不到,也会映射到内存中,不仅占用更多的内存,在执行效率方面

会有所降低,所以不要滥用抽象编程

8.避免使用依赖注入框架

使用依赖注入框架后会在初始化的过程中,历经较长的初始化的过程,用不到的注解对象也会加载到内存中,可能很久

之后才会得到释放

9.使用ProGuard混淆代码

ProGuard除了混淆代码之外,还具有压缩优化代码的功能,可以删除一些无用的代码,并对类、字段、方法

重命名,重命名之后,变得更加简短,更加节省内存

Proguard的路径在SDK目录下的tools中-----------studiosdk/tools/proguard

然后修改app的build下的buildTypes的minifyEnabled值为true,就可以混淆代码


buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}



10.使用多个线程
想使用多个线程很简单,只需在AndroidManifest.xml文件中的应用程序组件
中声明一个android:process属性即可
比如:我想让遍历文件夹的一个Service可以运行在一个单独的线程中:

<Service android:name = "FolderService" android:process = ":background">
</Service>