作业——在线学习Android课程之第十二周(内存优化)

来源:互联网 发布:淘宝起名字 编辑:程序博客网 时间:2024/06/01 08:43

一、内存调试工具的简介

MemoryMonitor, AllocationTracker以及HeapDump,LeakCanary

(1)、Memory Monitor

方便显示内存使用和GC情况快速定位卡顿是否与GC有关快速定位Crash是否和内存占用过高有关快速定位潜在的内存泄漏问题简单易用不能准确定位问题

(2)、Allocation Tracker

定位代码中分配的对象的类型,大小,时间,线程,堆栈等信息定位内存抖动问题配合Heap Viewer一起定位内存泄漏问题使用复杂

(3)、HeapDump

内存快照信息每次GC之后收集一次信息查找内存泄漏利器使用复杂

(4)、LeakCanary

查找内存泄漏利器

二、内存调试工具的调用方法

1、MemoryMonitor的调用方法

(1)选择“View”,选择“Tool Windows”,选择“Android Monitor”。
(2)在界面下方选择“Monitor”,往上滚动到“Memory”视图即可。

这里写图片描述

2、 AllocationTracker的调用方法

(1)在程序运行后,需要的时间点,点击“Start Allocation Tracking”,开启记录
(2)再次点击“Stop Allocation Tracking”,停止记录

这里写图片描述

(3)以”方法“或”对象“为目标查看

这里写图片描述

3、HeapDump的调用方法

(1)在程序运行后,需要的时间点,点击“Dump Java Heap”
(2)在弹出的新窗口内,可以选择以”Package Tree View“查看结果

这里写图片描述

4、LeakCanary的调用方法

(1)在build.gradle文件的依赖中添加

dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    testCompile 'junit:junit:4.12'    compile 'com.android.support:appcompat-v7:23.1.1'    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1    testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1}

(2)新建MyApplication类,以初始化LeakCanary

public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        LeakCanary.install(this);    }}

(3)别忘记在AndroidMainfest.xml中注册MyApplication

<application    android:name=".MyApplication"    ……   //其他代码</application>

(4)在调试时若出现内存泄漏即会弹出通知,点击后显示详情

这里写图片描述

三、内存调试工具的实际使用

下载bug项目:https://github.com/lzyzsd/MemoryBugs,请注意配合使用MemoryMonitor, AllocationTracker以及HeapDump,LeakCanary等工具来查找潜在的内存问题,并尝试解决。

1、

(1)、运行程序,查看MemoryMonitor,发现当点击“STARTALLOCATION”后出现内存抖动现象。

这里写图片描述

(2)、启用AllocationTracker,再点击“STARTALLOCATION”按钮,发现MainActivity创建了大量的Rect

这里写图片描述

(3)、在程序中找到相关代码

private void startAllocationLargeNumbersOfObjects() {    Toast.makeText(this, "请注意查看MemoryMonitor 以及AllocationTracker", Toast.LENGTH_SHORT).show();    for (int i = 0; i < 10000; i++) {        Rect rect = new Rect(0, 0, 100, 100);        System.out.println("-------: " + rect.width());    }}

(4)、将Rect的创建移出for循环

private void startAllocationLargeNumbersOfObjects() {    Toast.makeText(this, "请注意查看MemoryMonitor 以及AllocationTracker", Toast.LENGTH_SHORT).show();    Rect rect = new Rect(0, 0, 100, 100);    //将Rect的创建移出for循环    for (int i = 0; i < 10000; i++) {        System.out.println("-------: " + rect.width());    }}

2、

(1)、点击“STARTACTIVITYB”按钮后,若干秒后LeakCanary弹出内存泄漏通知

这里写图片描述

(2)、查看代码,MainActivity已finish()

private void startB() {    finish();    startActivity(new Intent(this, ActivityB.class));    mHandler.postDelayed(new Runnable() {        @Override        public void run() {            System.out.println("post delayed may leak");        }    }, 5000);    Toast.makeText(this, "请注意查看通知栏LeakMemory", Toast.LENGTH_SHORT).show();}

(3)、查看HeapDump,MainActivity未被销毁,与sTextView和Handler有关

这里写图片描述

(4)、修改代码,如下:

//    private static TextView sTextView;------------------------------------------------------------------    private TextView sTextView;==================================================================//    Handler mHandler = new Handler(new Handler.Callback() {//        @Override//        public boolean handleMessage(Message msg) {//            return false;//        }------------------------------------------------------------------    public MyHandler mHandler = new MyHandler(this);    public static class MyHandler extends Handler {        WeakReference<MainActivity > mActivityReference;        MyHandler(MainActivity activity) {            mActivityReference= new WeakReference<>(activity);        }        @Override        public void handleMessage(Message msg) {            final MainActivity activity = mActivityReference.get();            if (activity != null) {                return;            }        }    }

3、在onDraw方法中使用了“new”方法,移出

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        RectF rect =  new RectF(0, 0, 100, 100);        Paint paint = new Paint();        paint.setColor(Color.RED);        paint.setStrokeWidth(4);        canvas.drawArc(rect, 0, 180, true, paint);    }
0 0
原创粉丝点击