手把手教你在Android Studio 3.0上分析内存泄漏

来源:互联网 发布:个人怎么注册域名 编辑:程序博客网 时间:2024/06/01 09:37

戳我下载 Android Studio 3.0

这个不用梯子我会告诉你吗

1.写在前面

转载自http://blog.csdn.net/kong_gu_you_lan/article/details/78404209

2.强大的Android Profiler

戳这里查看官方文档

在3.0版本中,android使用了新的性能分析工具Android Profiler来代替原有的Android Monitor,使用方式和原来类似,都可以分析CPU、内存和网络的使用情况,但是功能强大了很多。

开始使用

还记得我之前写过一篇文章《Android 使用RxLifecycle解决RxJava内存泄漏》,本文将以这篇文章里的Demo为例,使用Android Studio 3.0再次分析一下内存泄漏。

首先点击工具栏中的Profile按钮将待分析的App安装到设备上,也可以直接安装,在AS底部选择Android Profiler按钮:

将待分析的APP安装到设备上

可以看到有下面的提示,大概意思是不能在当前进程进行更高级的分析:

不能在当前进程进行更高级的分析

点击Run Configuration进去看看,发现不能勾选开关,提示gradle插件版本太低,需要2.4以上版本才可以,嗯,那就更新一下:

更新gradle插件版本

已经更新到3.0版本了,可以勾选开关了,点击确定:

dependencies {    classpath 'com.android.tools.build:gradle:3.0.0'}
  • 1
  • 2
  • 3

勾选开关

又来一个警告,大概意思是说,你的gradle版本已经升级到3.0了,需要和26.0.2版本的构建工具搭配才更好,好好好,听你的:

更新26.0.2版本的构建工具

更新完成之后,需要再次运行一下App,如果还提示不能进行更高级的分析,请重启Android Studio,重启还不好,没关系,反正今天也用不到它,不要打我,下面来看下正常的Android Profiler:

Android Profiler

点击MEMORY进入内存详情,在这里可以实时查看内存的占用情况:

内存详情

内存泄漏分析

我们先写个会发生内存泄漏的程序分析一下:

public class RxLifecycleComponentsActivity extends RxAppCompatActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_rxlifecycle);        ButterKnife.bind(this);        initData();    }    private void initData() {        // 每隔1s执行一次事件        Observable.interval(1, TimeUnit.SECONDS)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<Long>() {                    @Override                    public void onSubscribe(@NonNull Disposable d) {                    }                    @Override                    public void onNext(@NonNull Long aLong) {                        Log.i("接收数据", String.valueOf(aLong));                    }                    @Override                    public void onError(@NonNull Throwable e) {                    }                    @Override                    public void onComplete() {                    }                });    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

很简单,每隔1s发送一条数据,因为关闭Activity之后没有取消订阅,RxJava还继续持有Activity的引用,所以在内存回收的时候,该Activity不会被回收,由此引发内存泄漏。

下面反复打开关闭页面5次,然后手动GC(点击左上角的垃圾桶图标),发现内存占用并没有减少:

内存泄漏分析

分析一下当前的内存堆栈情况(点击垃圾桶图标右侧的图标):

分析内存堆栈情况

选择按包名查找,找到当前测试的Activity,发现存在5个实例,由此可见,内存已经发生了泄漏:

内存泄漏

防止内存泄漏

修改一下上面的代码,在关闭Activity时取消订阅:

public class RxLifecycleComponentsActivity extends RxAppCompatActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_rxlifecycle);        ButterKnife.bind(this);        initData();    }    private void initData() {        // 每隔1s执行一次事件        Observable.interval(1, TimeUnit.SECONDS)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))                .subscribe(new Observer<Long>() {                    @Override                    public void onSubscribe(@NonNull Disposable d) {                    }                    @Override                    public void onNext(@NonNull Long aLong) {                        Log.i("接收数据", String.valueOf(aLong));                    }                    @Override                    public void onError(@NonNull Throwable e) {                    }                    @Override                    public void onComplete() {                    }                });    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

反复打开页面5次,手动GC,看下当前的堆栈情况,可以看到当前已经没有RxLifecycleComponentsActivity的实例存在了:

无内存泄漏

OK,到这里,在Android Studio 3.0上分析内存泄漏就学习完了,赶快去动手试试吧!

3.更新Android Studio遇到的问题

编译的时候报错:

Error:(41, 0) Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
  • 1

发现是在gradle里打包输出apk的代码出的问题,原代码是这样的:

applicationVariants.all { variant ->    variant.outputs.each { output ->        def file = output.outputFile        String apkName = "APK_NAME" + defaultConfig.versionName.replace(".", "_") + ".apk"        output.outputFile = new File(file.parent, apkName)    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

修改成这样就可以了:

applicationVariants.all { variant ->    variant.outputs.all {        outputFileName = "APK_NAME" + defaultConfig.versionName.replace(".", "_") + ".apk"    }}
  • 1
  • 2
  • 3
  • 4
  • 5

4.写在最后

戳我下载 Android Studio 3.0

戳我下载本文使用的测试Demo

原创粉丝点击