Android | Android性能优化工具之StrictMode

前言

StrictMode(严格模式)是一个开发工具,它可以检测出一些影响应用性能的问题。比如,在主线程中进行磁盘读写操作、Activity内存泄漏等。我们可以使用StrictMode来优化应用的性能,提高应用的响应能力,减少应用的内存泄露,避免应用出现ANR和OOM。

使用StrictMode

StrictMode支持两类检测策略:

  • ThreadPolicy(线程策略),主要可以检测主线程中的一些耗时操作。
  • VmPolicy(虚拟机策略),主要可以检测一些对象的泄漏。

配置ThreadPolicy

调用如下的静态方法可以开启ThreadPolicy检测:

StrictMode.setThreadPolicy(final ThreadPolicy policy);

ThreadPolicy对象的创建需要使用 StrictMode.ThreadPolicy.Builder 类,Builder类提供了一系列的方法来配置ThreadPolicy的检测内容。如下表所示:

方法说明
detectDiskReads()开启磁盘读操作检测
detectDiskWrites()开启磁盘写操作检测
detectNetwork()开启网络操作检测
detectCustomSlowCalls()开启耗时调用检测
detectResourceMismatches()开启资源类型和获取调用不匹配检测
detectAll()开启ThreadPolicy支持的所有检测

同时,Builder类提供了方法来配置当检测到ThreadPolicy类型的违规时该如何处理。如下表所示:

方法说明
penaltyLog()记录Log
penaltyDropBox()记录Log到DropBox
penaltyFlashScreen()闪烁屏幕
penaltyDialog()弹出对话框
penaltyDeath()杀死应用进程
penaltyDeathOnNetwork()当检测到网络操作时杀死应用进程

配置ThreadPolicy的示例代码如下所示:

StrictMode.ThreadPolicy threadPolicy = new StrictMode.ThreadPolicy.Builder()
        .detectDiskReads()
        .detectDiskWrites()
        .penaltyFlashScreen()
        .penaltyLog()
        .build();
StrictMode.setThreadPolicy(threadPolicy);

配置VmPolicy

调用如下的静态方法可以开启VmPolicy检测:

StrictMode.setVmPolicy(final VmPolicy policy);

与ThreadPolicy类似,VmPolicy对象的创建需要使用 StrictMode.VmPolicy.Builder 类,Builder类提供了一系列的方法来配置VmPolicy的检测内容。如下表所示:

方法说明
detectActivityLeaks()开启Activity泄漏检测
detectLeakedClosableObjects()开启Closeable对象未关闭泄漏检测
detectLeakedSqlLiteObjects()开启SQLite对象未关闭泄漏检测
detectLeakedRegistrationObjects()开启BroadcastReceiver/ServiceConnection泄漏检测
detectFileUriExposure()开启文件URI暴露检测
detectCleartextNetwork()开启明文网络流量检测
detectAll()开启VmPolicy支持的所有检测

同时,Builder类提供了方法来配置当检测到VmPolicy类型的违规时该如何处理。如下表所示:

方法说明
penaltyLog()记录Log
penaltyDropBox()记录Log到DropBox
penaltyDeath()杀死应用进程
penaltyDeathOnFileUriExposure()当检测到文件URI暴露时杀死应用进程
penaltyDeathOnCleartextNetwork()当检测到明文网络流量时杀死应用进程

配置VmPolicy的示例代码如下所示:

StrictMode.VmPolicy vmPolicy = new StrictMode.VmPolicy.Builder()
        .detectActivityLeaks()
        .detectLeakedClosableObjects()
        .detectLeakedSqlLiteObjects()
        .penaltyLog()
        .build();
StrictMode.setVmPolicy(vmPolicy);

开启StrictMode

通常,在应用的Application类、Activity类,或者其它应用组件的onCreate()方法的开始处开启StrictMode。示例代码如下所示:

@Override
public void onCreate() {
    // Debug模式下开启严格模式
    if (BuildConfig.DEBUG) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .penaltyFlashScreen()
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());
    }
    super.onCreate();
    ...
}

注意: 应该在Debug模式下才开启StrictMode。

我们可以使用 StrictMode 关键字来过滤系统日志,根据StrictMode日志我们就可以优化应用了。当检测到在主线程中执行了磁盘读操作时,打印的Log如下所示:

12-07 22:03:30.272 11351-11351/com.github.cyc.performance.strictmodedemo D/StrictMode: StrictMode policy violation; ~duration=2 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=1114143 violation=2
        at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1263)
        at libcore.io.BlockGuardOs.read(BlockGuardOs.java:229)
        at libcore.io.IoBridge.read(IoBridge.java:468)
        at java.io.FileInputStream.read(FileInputStream.java:177)
        at java.io.InputStreamReader.read(InputStreamReader.java:233)
        at java.io.BufferedReader.fillBuf(BufferedReader.java:145)
        at java.io.BufferedReader.readLine(BufferedReader.java:397)
        at com.github.cyc.performance.strictmodedemo.FileUtils.readFile(FileUtils.java:22)
        at com.github.cyc.performance.strictmodedemo.MainActivity.onClick(MainActivity.java:48)
        at android.view.View.performClick(View.java:5207)
        at android.view.View$PerformClick.run(View.java:21177)
        at android.os.Handler.handleCallback(Handler.java:742)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:5524)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:630)

当检测到在主线程中执行了磁盘写操作时,打印的Log如下所示:

12-07 22:07:43.083 11351-11351/com.github.cyc.performance.strictmodedemo D/StrictMode: StrictMode policy violation; ~duration=1 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=1114143 violation=1
        at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1223)
        at libcore.io.BlockGuardOs.write(BlockGuardOs.java:312)
        at libcore.io.IoBridge.write(IoBridge.java:493)
        at java.io.FileOutputStream.write(FileOutputStream.java:186)
        at java.io.OutputStreamWriter.flushBytes(OutputStreamWriter.java:170)
        at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:161)
        at java.io.BufferedWriter.flush(BufferedWriter.java:124)
        at com.github.cyc.performance.strictmodedemo.FileUtils.writeFile(FileUtils.java:52)
        at com.github.cyc.performance.strictmodedemo.MainActivity.onClick(MainActivity.java:53)
        at android.view.View.performClick(View.java:5207)
        at android.view.View$PerformClick.run(View.java:21177)
        at android.os.Handler.handleCallback(Handler.java:742)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:5524)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:630)

最后要注意:

  • 在正常的Activity生命周期中,有些磁盘操作是必要的。
  • StrictMode无法检测来自JNI调用的磁盘和网络操作。

总结

我们可以使用StrictMode来优化应用的性能,提高应用的响应能力,减少应用的内存泄露,避免应用出现ANR和OOM。

参考

  • Android 7.1.1 (API level 25)
  • https://developer.android.com/reference/android/os/StrictMode.html
  • https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html
  • https://developer.android.com/reference/android/os/StrictMode.VmPolicy.Builder.html
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值