Android性能优化之内存优化

作者:jcmp      发布时间:2021-04-23      浏览量:0
导读读完本篇能学到以下知识内存优化是An

导读

读完本篇能学到以下知识

内存优化是Android中优化的一个重点,内存优化不到位会引起频繁的GC,导致耗电严重.

要做内存优化首先要找到优化的对象.在Android开发中有两个内存大户,Activity和Bitmap.Activity主要是防止内存泄漏,Bitmap需要防止oom。

Activity的内存泄漏

所谓内存泄漏就是这个对象至少有一条到达根节点的路径. 那有哪些是根节点呢? Java虚拟机中的根节点如下:

还有比较隐蔽的内部类,内部类会默认持有外部类的引用要注意下. 内存泄漏情景。

public class TestActivity extends Activity{ public static List list = new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { ... list.add(this); }}

解决方法:及时remove会避免静态引用持有.

public class TestActivity extends Activity{ Handler handler = new Handler(){ @Override public void handleMessage(){ ... } }; @Override protected void onCreate(Bundle savedInstanceState) { ... handler.sendMessageDelay(msg, 100000); }}

因为handler现在是个匿名内部类,所以持有Activity的引用,一旦有未发送的Message,Activity就会内存泄漏.

解决方法

1. 在onDestroy()里让handler移除所有消息

Activity:... @Override protected void onCreate(Bundle savedInstanceState) { handler.removeMessage(...); }...

2. 定义一个继承Handler的static类,用WeakReference持有Activity(如果需要调用Activity的话)。

class Activity{ MyHandler handler; @Override protected void onCreate(Bundle savedInstanceState) { handler = new MyHandler(this); } private static class MyHandler extends Handler{ private WeakReference weakRef; public Handler(Context context){ weakRef = new WeakReference<>(context); } @Override public void handleMessage(){ ... } }}

class Activity{ @Override protected void onCreate(Bundle savedInstanceState) { ... new Thread(new Runnable(){ @Override public void run(){ //耗时操作 } }).start(); } }

解决线程导致的内存泄漏跟Handler类似

1. 在onDestroy()里调用Thread.interrupt()结束线程2. 把线程定义成静态内部类用WeakReference持有Activity。

检测内存泄漏方法

用这个命令开始的时候打印一次,然后打开关闭泄漏Activity一定次数,接着触发GC(Profile里Memory的垃圾桶图标),最后再打印一次这个命令,看看两次Activities的数量差是否和打开泄漏Activity次数一样.如果不一样说明部分(GC并不一定回收所有对象)Activity已经被回收了,没有内存泄露.反之则内存泄漏.

Views: 189 ViewRootImpl: 1 AppContexts: 11 Activities: 1 Assets: 2 AssetManagers: 2 Local Binders: 15 Proxy Binders: 25 Parcel memory: 4 Parcel count: 16Death Recipients: 0 OpenSSL Sockets: 0。

Activity: public static List list = new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... list.add(this); }

具体操作如下:

Bitmap优化

Bitmap bm;BitmapFactory.Options opt = new BitmapFactory.Options(); //设置只加载大小不加载像素数据opt.inJustDecodeBounds = true;bm = BitmapFactory.decodeFile(absolutePath, opt);//计算出你需要的比例opt.inSampleSize = bm.getHeight()/neededHeight;//伪代码//inJustDecodeBounds设为true去加载像素数据opt.inJustDecodeBounds = false;bm = BitmapFactory.decodeFile(absolutePath, opt);

就是先加载原始图的大小,接着计算出需要的比例传给inSampleSize,再加载一遍图片.

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }

这时LinkedHashMap就会生成一个双端队列,get的时候把值插到最前面实现Lru的策略效果,实现原理可以参考 这篇文章 .