Android中的StrictMode
2014-10-09 09:44
288 查看
Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益。那它都做什么呢?它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy
violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。你可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的应用继续执行。策略的细节尚难确定,可以期待随Android的成熟Google将增加更多策略。
目前有2种策略可用,第一个和线程相关,它主要针对主线程(或UI线程)。由于在主线程中读写磁盘和进行网络访问都不是好的做法,Google已经在磁盘和网络代码中添加了严苛模式(StrictMode)钩子(hook)。如果你对某个线程打开严苛模式(StrictMode),当那个线程进行磁盘和网络访问,你将获得警告。你可以选择警告方式。一些违例包含用户慢速调用(custom slow calls 这么翻译行吗?),磁盘读写,网络访问。你能选择将警告写入LogCat,显示一个对话框,闪下屏幕,写入DropBox日志文件,或让应用崩溃。最通常的做法是写入LogCat或让应用崩溃。
写程序时,你应该始终假定下列两种情况:
网络很慢(你正在试图连接的服务器甚至可能没有响应);
文件系统的访问速度很慢。
结论就是,不应该在主线程内进行网络操作或访问文件系统,因为缓慢的操作会拖累系统的响应能力。虽然在开发环境中,你可能永远不会遇到任何网络问题或任何文件系统的性能问题,但用户可能不像你那么幸运。
注意 SD卡并不都具有相同“速度”,如果应用在很大程度上依赖外部存储设备的性能,那么你应该确保在来自不同制造商的各种SD卡上测试过你的应用。
Android有实用工具来帮助应用检测这类缺陷。它提供的StrictMode是检测不良行为的良好工具。通常情况下,在应用启动时,即当onCreate()被调用时,启用StrictMode,如代码清单1-15所示。
在应用中启用StrictMode
[java] view plaincopy
public class MyApplication extends Application {
@Override
public void onCreate () {
super.onCreate();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls()// API等级11,使用StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyFlashScreen()// API等级11
.build());
// 其实和性能无关,但如果使用StrictMode,最好也定义VM策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()// API等级11
.setClassInstanceLimit(Class.forName("com.apress.proandroid.SomeClass", 100)// API等级11
.penaltyLog()
.build());
}
}
StrictMode是Android 2.3引入的,在Android 3.0中加入了更多的功能,所以应该确保选择了正确的Android版本,让代码跑在适当的Android平台上,如代码清单1-12所示。
Android 3.0中引入的需要特别留意的方法包括detectCustomSlowCall()和noteSlowCall(),它们都是用来检测应用中执行缓慢的代码或潜在缓慢的代码。代码清单1-16说明了如何将代码标记为潜在缓慢的代码。
代码清单1-16 标记潜在缓慢的代码
[java] view plaincopy
public class Fibonacci {
public static BigInteger computeRecursivelyWithCache(int n) {
StrictMode.noteSlowCall("computeRecursivelyWithCache");// 消息可以带任何信息
SparseArray cache = new SparseArray();
return computeRecursivelyWithCache(n, cache);
}
...
}
[java] view plaincopy
[java] view plaincopy
public class Fibonacci {
public static BigInteger computeRecursivelyWithCache(int n) {
StrictMode.noteSlowCall("computeRecursivelyWithCache");// 消息可以带任何信息
SparseArray cache = new SparseArray();
return computeRecursivelyWithCache(n, cache);
}
...
}
从主线程调用computeRecursivelyWithCache执行时间过长,如果StrictMode Thread 策略配置为检测缓慢调用时,会出现如下日志:
[java] view plaincopy
StrictMode policy violation; ~duration=21121 ms:
android.os.StrictMode$StrictModeCustomViolation: policy=31 violation=8 msg=computeRecursivelyWithCache
StrictMode policy violation; ~duration=21121 ms:
android.os.StrictMode$StrictModeCustomViolation: policy=31 violation=8 msg=computeRecursivelyWithCache
Android提供了一些辅助方法,可以在主线程里进行临时磁盘读写,如代码
[java] view plaincopy
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
修改线程策略,临时允许磁盘读取
[java] view plaincopy
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
// 从磁盘读取数据
StrictMode.setThreadPolicy(oldPolicy);
目前没有临时允许网络访问的方法,但实在没有理由在主线程中允许这种访问,即使是暂时的,也没有合适的方式知道访问是否很快。有人可能会说,也没有合理的方式知道磁盘访问将是否是快速的,但那是另一场争论。
注意 只在开发阶段启用StrictMode,发布应用时,记得要禁用它。如果你使用detectAll()方法去建立策略总是可行的,那将来更可行,未来的Android版本会检测出更多的不良行为。
violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。你可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的应用继续执行。策略的细节尚难确定,可以期待随Android的成熟Google将增加更多策略。
目前有2种策略可用,第一个和线程相关,它主要针对主线程(或UI线程)。由于在主线程中读写磁盘和进行网络访问都不是好的做法,Google已经在磁盘和网络代码中添加了严苛模式(StrictMode)钩子(hook)。如果你对某个线程打开严苛模式(StrictMode),当那个线程进行磁盘和网络访问,你将获得警告。你可以选择警告方式。一些违例包含用户慢速调用(custom slow calls 这么翻译行吗?),磁盘读写,网络访问。你能选择将警告写入LogCat,显示一个对话框,闪下屏幕,写入DropBox日志文件,或让应用崩溃。最通常的做法是写入LogCat或让应用崩溃。
写程序时,你应该始终假定下列两种情况:
网络很慢(你正在试图连接的服务器甚至可能没有响应);
文件系统的访问速度很慢。
结论就是,不应该在主线程内进行网络操作或访问文件系统,因为缓慢的操作会拖累系统的响应能力。虽然在开发环境中,你可能永远不会遇到任何网络问题或任何文件系统的性能问题,但用户可能不像你那么幸运。
注意 SD卡并不都具有相同“速度”,如果应用在很大程度上依赖外部存储设备的性能,那么你应该确保在来自不同制造商的各种SD卡上测试过你的应用。
Android有实用工具来帮助应用检测这类缺陷。它提供的StrictMode是检测不良行为的良好工具。通常情况下,在应用启动时,即当onCreate()被调用时,启用StrictMode,如代码清单1-15所示。
在应用中启用StrictMode
[java] view plaincopy
public class MyApplication extends Application {
@Override
public void onCreate () {
super.onCreate();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls()// API等级11,使用StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyFlashScreen()// API等级11
.build());
// 其实和性能无关,但如果使用StrictMode,最好也定义VM策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()// API等级11
.setClassInstanceLimit(Class.forName("com.apress.proandroid.SomeClass", 100)// API等级11
.penaltyLog()
.build());
}
}
StrictMode是Android 2.3引入的,在Android 3.0中加入了更多的功能,所以应该确保选择了正确的Android版本,让代码跑在适当的Android平台上,如代码清单1-12所示。
Android 3.0中引入的需要特别留意的方法包括detectCustomSlowCall()和noteSlowCall(),它们都是用来检测应用中执行缓慢的代码或潜在缓慢的代码。代码清单1-16说明了如何将代码标记为潜在缓慢的代码。
代码清单1-16 标记潜在缓慢的代码
[java] view plaincopy
public class Fibonacci {
public static BigInteger computeRecursivelyWithCache(int n) {
StrictMode.noteSlowCall("computeRecursivelyWithCache");// 消息可以带任何信息
SparseArray cache = new SparseArray();
return computeRecursivelyWithCache(n, cache);
}
...
}
[java] view plaincopy
[java] view plaincopy
public class Fibonacci {
public static BigInteger computeRecursivelyWithCache(int n) {
StrictMode.noteSlowCall("computeRecursivelyWithCache");// 消息可以带任何信息
SparseArray cache = new SparseArray();
return computeRecursivelyWithCache(n, cache);
}
...
}
从主线程调用computeRecursivelyWithCache执行时间过长,如果StrictMode Thread 策略配置为检测缓慢调用时,会出现如下日志:
[java] view plaincopy
StrictMode policy violation; ~duration=21121 ms:
android.os.StrictMode$StrictModeCustomViolation: policy=31 violation=8 msg=computeRecursivelyWithCache
StrictMode policy violation; ~duration=21121 ms:
android.os.StrictMode$StrictModeCustomViolation: policy=31 violation=8 msg=computeRecursivelyWithCache
Android提供了一些辅助方法,可以在主线程里进行临时磁盘读写,如代码
[java] view plaincopy
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
修改线程策略,临时允许磁盘读取
[java] view plaincopy
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
// 从磁盘读取数据
StrictMode.setThreadPolicy(oldPolicy);
目前没有临时允许网络访问的方法,但实在没有理由在主线程中允许这种访问,即使是暂时的,也没有合适的方式知道访问是否很快。有人可能会说,也没有合理的方式知道磁盘访问将是否是快速的,但那是另一场争论。
注意 只在开发阶段启用StrictMode,发布应用时,记得要禁用它。如果你使用detectAll()方法去建立策略总是可行的,那将来更可行,未来的Android版本会检测出更多的不良行为。
相关文章推荐
- android 2.3 api StrictMode
- java.lang.NoClassDefFoundError: android.os.StrictMode$ThreadPolicy$Builder
- Android用HTTP下载报错“android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork”
- Android内存泄露分析之StrictMode
- Android StrictMode严格模式的使用方法
- StrictMode.StrictMode$AndroidBlockGuardPolicy.onNetwork
- android 内存泄露分析 Lint StrictMode LeakCanary Memory Analyzer (MAT)
- android错误:at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
- at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
- Android Studio StrictMode
- android StrictMode
- android 严苛模式(StrictMode)——StrictMode.setThreadPolicy
- at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(错误
- Android之StrictMode应用性能分析
- android 严苛模式(StrictMode)——StrictMode.setThreadPolicy
- android之StrictMode介绍
- Android的StrictMode
- Android的StrictMode
- Android StrictMode 严苛模式
- Android性能调优利器StrictMode