1.一个app对应一个进程分配一个虚拟机
2.查看进程,进入adb目录
adb shell
ps
dumpsys meminfo com.ioter.cloth(进程名称/应用包名)
3.内存查看
As Android Monitor
Android Monitor Device(DDMS,查看堆内存分配情况)
4.内存优化
a.数据结构优化
字符串拼接,用StringBuilder 而不用String
ArrayMap/SparseArray替换HashMap
内存抖动
(频繁分配内存空间,而gc又去销毁)
b.对象复用
复用系统自带资源
ListView/GridView的ConvertView复用
避免在onDraw中创建对象
c.内存泄漏
(内存块被其它引用,导致gc无法回收)
内存泄漏会导致剩余可用Heap越来越少,频繁触发GC
尤其Activity泄漏
用Application Context而不是Activity Context
Cursor关闭
5.OOM(大部分发生在图片的oom)
图片的处理
强引用和软引用(SoftReference mp)
a 临时Bitmap对象及时回收
b 避免Bitmap浪费
c Try catch大内存分配操作
d 加载Bitmap:缩放比例/解码格式/局部加载
6.检查UI卡顿
a 设置主线程发送消息处理时间的logging打印,
public class BlockDetectByPrinter
{
public static void start()
{
Looper.getMainLooper().setMessageLogging(new Printer()
{
private static final String START = ">>>>> Dispatching";//跟message处理的log标识一样
private static final String END = "<<<<< Finished";
@Override
public void println(String x)
{
if (x.startsWith(START))
{
LogMonitor.getInstance().startMonitor();
}
if (x.startsWith(END))
{
LogMonitor.getInstance().removeMonitor();
}
}
});
}
}
b 开启打印主线程超时的子线程
public class LogMonitor
{
private static LogMonitor sInstance = new LogMonitor();
private HandlerThread mLogThread = new HandlerThread("log");
private Handler mIoHandler;
private static final long TIME_BLOCK = 1000L;//超过1s就打印超时的原因log
private LogMonitor()
{
mLogThread.start();
mIoHandler = new Handler(mLogThread.getLooper());
}
private static Runnable mLogRunnable = new Runnable()
{
@Override
public void run()
{
StringBuilder sb = new StringBuilder();
StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace();
for (StackTraceElement s : stackTrace)
{
sb.append(s.toString() + "\n");
}
Log.e("TAG", sb.toString());
}
};
public static LogMonitor getInstance()
{
return sInstance;
}
public void startMonitor()
{
mIoHandler.postDelayed(mLogRunnable, TIME_BLOCK);
}
public void removeMonitor()
{
mIoHandler.removeCallbacks(mLogRunnable);
}
}