Android性能优化工具之StrictMode

来源:互联网 发布:java属性签名是什么 编辑:程序博客网 时间:2024/06/04 09:06

前言

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。示例代码如下所示:

@Overridepublic 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
原创粉丝点击