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

一、内存调试工具的简介

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值