使用StrictMode优化Android应用程序的ANR率
本文将解释StrictMode是什么以及如何在Android应用程序中使用它作为ANR观察器。
什么是StrictMode以及为什么使用它?
StrictMode是帮助开发人员防止ANR并减少在Android系统中产生ANR的机会的工具之一。
从developer.android.com上可以得知,使用StrictMode有助于在开发应用程序时找到在主线程上意外进行的I/O操作。
https://developer.android.com/topic/performance/vitals/anr?hl=zh-cn
我们可以将StrictMode用作分析器工具,它在运行时分析应用程序进程的主线程。它基于两种策略模型工作,如果违反了任何策略,则会采取相应的措施。
StrictMode策略
线程策略
磁盘读取、磁盘写入、网络、资源不匹配和缓慢代码
VM策略
Activity泄漏、SQLite对象、可关闭对象、对象泄漏和文件URL暴露。
正如我们所知,ANR与主线程上的资源密集型任务相关,因此StrictMode启用了所有可能导致ANR的原因,将其视为策略违规。
如何实施StrictMode?
在学习如何在任何Android进程中使用StrictMode时,让我们通过一个实际示例看看StrictMode策略违规。
首先,我们可以创建一个简单的单页面默认的“Hello World!” Android应用程序,并在其中初始化一个文本视图。
public class MainActivity extends AppCompatActivity {
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = findViewById(R.id.text);
}
}
让我们在UI线程上执行一些耗时操作。所以最简单的方法是编写一个while循环,并在其中无限更新一个文本视图,这肯定会导致ANR。
@Override
public boolean onTouchEvent(MotionEvent event) {
while(true) {
String s = new String("ABC");
text.setText(s);
}
}
当您在屏幕上触摸任何位置时,希望您能看到ANR对话框出现在您的应用程序中。
现在,您可以将StrictMode启用代码添加到主活动的onCreate方法中。
原则上,这段代码应该添加到Application类中,但为了更容易理解概念,我们不必让它变得更复杂。
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
现在运行应用程序并观察行为!!
在下面的视频中,可以看到当我启用StrictMode策略后,应用程序直接崩溃,而不是显示ANR对话框,并且在日志中记录了StrictMode违规。
D StrictMode policy violation: android.os.strictmode.LeakedClosableViolation:
A resource was acquired at attached stack trace but never released.
See java.io.Closeable for information on avoiding resource leaks.
Callsite: close
at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1991)
at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:338)
at sun.nio.fs.UnixSecureDirectoryStream.finalize(UnixSecureDirectoryStream.java:580)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:319)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:306)
at java.lang.Daemons$Daemon.run(Daemons.java:140)
at java.lang.Thread.run(Thread.java:1012)
W StrictMode VmPolicy violation with POLICY_DEATH; shutting down.
I Sending signal. PID: 20526 SIG: 9
I Process com.example.anrexample (pid 20526) has died: fg TOP
I WIN DEATH: Window{afd4cf6 u0 com.example.anrexample/com.example.anrexample.MainActivity}
I Successfully killed process cgroup uid 10163 pid 20526 in 0ms
正如我们所见,StrictMode可以帮助检测策略违规并使应用程序崩溃。
结论
Android在处理由应用程序在运行时引入的许多问题情况方面表现出色,在处理ANR方面也是如此,通过在UI线程上维持5秒钟的资源密集型任务。
然而,作为程序员,我们有责任遵循框架给出的编程标准,因为超过5秒后,ANR将成为糟糕用户体验的结果。
因此,首先我们需要遵循所有的编码标准以预防ANR,并且如果有什么需要改进的地方,可以使用StrictMode作为工具,以免因疏忽而留下意外。