,,Android严苛模式StrictMode使用详解

,,Android严苛模式StrictMode使用详解

StrictMode类是Android 2.3 (API 9)推出的一个工具类,可以用来帮助开发者发现代码中的一些非标准问题,从而提高应用的响应性。

StrictMode类是Android 2.3 (API 9)推出的一个工具类,可以用来帮助开发者发现代码中的一些非标准问题,从而提高应用的响应性。比如开发者在UI线程中操作网络或文件系统,这些缓慢的操作会严重影响应用的响应速度,甚至会出现ANR对话框。为了在开发中发现这些容易被忽略的问题,我们使用StrictMode,系统检测主线程的违规行为并做出相应的响应,最终帮助开发人员优化和改进代码逻辑。

官网:3358 developer . Android . com/reference/Android/OS/strict mode . html

StrictMode具体能检测什么

严格模式主要检测两大问题,一是线程策略,即TreadPolicy,二是VmPolicy,即VM策略。

ThreadPolicy线程策略检测

线程策略检测的内容包括

的自定义耗时调用是通过detectCustomSlowCalls()启动的

使用detectDiskReads()启动磁盘读取操作。

磁盘写操作是用detectDiskWrites()启动的

网络操作由detectNetwork()启动。

VmPolicy虚拟机策略检测

使用detectActivityLeaks()打开活动泄漏。

未关闭的可关闭对象泄漏通过使用detectLeakedClosableObjects()打开

泄漏的Sqlite对象是用detectLeakedSqlLiteObjects()打开的

检测实例的数量由setClassInstanceLimit()决定

工作原理

其实StrictMode的实现原理比较简单。以IO操作为例,主要是在打开、读取、写入和关闭过程中被监控。文件libcore.io.BlockGuardOs是监控的地方。以open为例,监控如下。

@覆盖

公共FileDescriptor open(String path,int flags,int mode)引发ErrnoException {

BlockGuard.getThreadPolicy()。onReadFromDisk();

if ((mode O_ACCMODE)!=O _ r only){

BlockGuard.getThreadPolicy()。onWriteToDisk();

}

返回os.open(路径、标志、模式);

}

实现了onReadFromDisk()方法,代码位于StrictMode.java。

public void onReadFromDisk() {

if((mPolicyMask DETECT _ DISK _ READ)==0){

返回;

}

if(toomanviolationthisloop()){

返回;

}

街区守卫。BlockGuardPolicyException e=new StrictModeDiskReadViolation(mPolicyMask);

e . fillinstacktrace();

startHandlingViolationException(e);

}

常见用法

严格模式开放可以放在应用程序或活动的onCreate方法和其他组件中。为了更好的分析应用中的问题,建议放在应用的onCreate方法中。

其中,我们只需要在app的开发版中使用StrictMode,避免在网络版中使用StrictMode。这里定义了一个布尔变量DEV_MODE来控制。

私有布尔DEV _ MODE=true

public void onCreate() {

if(开发模式){

StrictMode.setThreadPolicy(新StrictMode。ThreadPolicy.Builder()。detectCustomSlowCalls() //API级别11,使用StrictMode.noteSlowCode。detectDiskReads()。detectDiskWrites()。detectNetwork() //或。detectAll()用于所有可检测的问题。penaltyDialog() //弹出违规提示对话框。penaltyLog() //在Logcat中打印违规异常信息。penaltyFlashScreen() //API级别11。build());

StrictMode.setVmPolicy(新StrictMode。VmPolicy.Builder()。detectLeakedSqlLiteObjects()。detectleakedclosableobjects()//API级别11。penaltyLog()。penaltyDeath()。build());

}

super . oncreate();

}

其中,Android3.0引入的方法有detectCustomSlowCalls()和noteSlowCode(),这两种方法都是用来检测应用中的慢代码或潜在的慢代码。

查看报告结果

在StrictMode中有多种报告违规的形式,但是如果您想要分析特定的违规,您仍然需要检查日志。在终端下过滤严格模式,可以得到具体的违规stacktrace信息。

亚洲开发银行日志|严格模式

当然,你也可以选择弹窗简洁地提醒开发者。

弹出警告

ThreadPolicy 详解

严格模式。线程策略。生成器主要方法如下

检测网络()用于检查用户界面线程中是否有网络请求操作

检测用户界面线程中网络请求案例:

公共类主要活动扩展AppCompatActivity实现视图OnClickListener {

按钮btnTest

@覆盖

受保护的void onCreate(Bundle saved instancestate){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。活动_主);

StrictMode.setThreadPolicy(新严格模式.线程策略。构建器()。检测网络()。penaltyLog()。build());

BTN测试=(Button)findViewById(r . id。BTN _测试);

btntest。setonclicklistener(this);

}

@覆盖

公共void onClick(视图五){

int id=v . getid();

开关(id) {

案例编号btn_test:

邮网();

打破;

}

}

/**

* 网络连接的操作

*/

私有void postNetwork() {

尝试{

URL URL=新URL(' http://www。宇云。org’);

http URL connection conn=(http URL connection)URL。打开连接();

conn . connect();

缓冲读取器reader=新缓冲读取器(新输入流读取器(

conn . getinputstream()));

字符串行=空

字符串缓冲区sb=新字符串缓冲区();

while ((lines=reader.readLine())!=null) {

某人追加(行);

}

} catch(异常e) {

e。printstacktrace();

}

}

}

运行后,触发的警告如下

detectDiskReads()和detectDiskWrites()是磁盘读写检查

磁盘读写检查案例:

公共类主要活动扩展AppCompatActivity实现视图OnClickListener {

按钮btnTest

@覆盖

受保护的void onCreate(Bundle saved instancestate){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。活动_主);

StrictMode.setThreadPolicy(新严格模式.线程策略。构建器()。detectDiskWrites()。detectDiskReads()。penaltyLog()。build());

BTN测试=(Button)findViewById(r . id。BTN _测试);

btntest。setonclicklistener(this);

}

@覆盖

公共void onClick(视图五){

int id=v . getid();

开关(id) {

案例编号btn_test:

writeToExternalStorage();

打破;

}

}

/**

* 文件系统的操作

*/

public void writeToExternalStorage(){

文件外部存储=环境。getexternal存储目录();

文件MB文件=新文件(外部阶段,' casti El。txt’);

尝试{

输出流output=新文件输出流(MB文件,true);

output.write('www.wooyun.org ').getBytes());

输出。flush();

输出。close();

} catch(找不到文件异常e){

e。printstacktrace();

} catch (IOException e) {

e。printstacktrace();

}

}

}

运行后,触发的警告如下

noteSlowCall针对执行比较耗时的检查

严格模式从API 11开始允许开发者自定义一些耗时调用违例,这种自定义适用于自定义的任务执行类中,比如我们有一个进行任务处理的类,为任务执行者。

公共类任务执行者{

公共void execute(可运行任务){

task.run()。

}

}

先需要跟踪每个任务的耗时情况,如果大于500毫秒需要提示给开发者,noteSlowCall就可以实现这个功能,如下修改代码

公共类任务执行者{

私有静态长慢速呼叫阈值=500

公共void执行任务(可运行任务){

长启动时间=系统时钟。正常运行时间millis();

task.run()。

长成本=系统时钟。uptime millis()-开始时间;

如果(慢成本呼叫阈值){

严格模式。notes低呼('慢呼成本='成本);

}

}

}

执行一个耗时2000毫秒的任务

任务执行者executor=新任务执行者();

执行者.执行任务(新的Runnable() {

@覆盖

公共无效运行(){

尝试{

线程。睡眠(2000年);

} catch (InterruptedException e) {

e。printstacktrace();

}

}

});

得到的违例日志,注意其中~持续时间=20毫秒并非耗时任务的执行时间,而我们的自定义信息消息=慢速呼叫成本=2000才包含了真正的耗时。

penaltyDeath(),当触发违规条件时,直接碰撞掉当前应用程序。

penaltyDeathOnNetwork(),当触发网络违规时,崩溃掉当前应用程序。

penaltyDialog(),触发违规时,显示对违规信息对话框。

penaltyFlashScreen(),会造成屏幕闪烁,不过一般的设备可能没有这个功能。

penaltyDropBox(),将违规信息记录到dropbox系统日志目录中(/data/system/dropbox),你可以通过如下命令进行插件:

ADB shell转储系统Dropbox dataappstrictmode-打印

permitCustomSlowCalls()、permitDiskReads()、permitdiskwests()、permitNetwork:如果你想关闭某一项检测,可以使用对应的许可证*方法。

VMPolicy 详解

严格模式。虚拟机策略生成器主要方法如下

detectActivityLeaks()用户检查活动的内存泄露情况

内存泄露检查案例:

公共类主要活动扩展AppCompatActivity实现视图OnClickListener {

@覆盖

受保护的void onCreate(Bundle saved instancestate){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。活动_主);

StrictMode.setVmPolicy(新严格模式.虚拟机策略。构建器()。detectActivityLeaks()。penaltyLog()。构建()

);

新线程(){

@覆盖

公共无效运行(){

while (true) {

系统时钟。睡眠(1000);

}

}

}.start();

}

}

我们反复旋转屏幕就会输出提示信息(重点在实例=2;极限=1这一行)

这时因为,我们在活动中创建了一个线匿名内部类,而匿名内部类隐式持有外部类的引用。而每次旋转屏幕是,安卓会新创建一个活动,而原来的活动实例又被我们启动的匿名内部类线程持有,所以不会释放,从日志上看,当先系统中该活动有四个实例,而限制是只能创建一各实例。我们不断翻转屏幕,实例的个数还会持续增加。

detectLeakedClosableObjects()用于资源没有正确关闭时提醒

//资源引用没有关闭检查案例

公共类主要活动扩展AppCompatActivity实现视图OnClickListener {

@覆盖

受保护的void onCreate(Bundle saved instancestate){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。活动_主);

StrictMode.setVmPolicy(新严格模式.虚拟机策略。构建器()。detectLeakedClosableObjects()。penaltyLog()。构建()

);

File new xmlfile=新文件(环境。getexternalstoratedirectory(),' casti El。txt’);

尝试{

新XML文件。创建新文件();

FileWriter fw=new FileWriter(新的XML文件);

fw.write('猴子搬来的救兵woo yun’);

//fw。close();我们在这里特意没有关闭淡水

} catch (IOException e) {

e。printstacktrace();

}

}

}

运行后触发警告如下

detectLeakedSqlLiteObjects()和

detectLeakedClosableObjects()的用法类似,只不过是用来检查SQLiteCursor或者其他SQLite

对象是否被正确关闭

detectLeakedRegistrationObjects()用来检查广播接收机或者

服务连接注册类对象是否被正确释放

setClassInstanceLimit(),设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露

检测内存泄露案例

公共类主要活动扩展AppCompatActivity实现视图OnClickListener {

私有静态类CastielClass{}

私有静态ListCastielClass类别列表

@覆盖

受保护的void onCreate(Bundle saved instancestate){

超级棒。oncreate(savedInstanceState);

setContentView(r . layout。活动_主);

class list=new ArrayListCastielClass();

StrictMode.setVmPolicy(新严格模式.虚拟机策略。构建器()。setClassInstanceLimit(castielclass。第二类)。penaltyLog()。build());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

班级名单。add(new casti El class());

}

}

运行后触发警告如下

其他操作

除了查看日志,我们还可以在开发人员选项中打开严格模式。开启后,如果主线程中有长时间运行的操作,屏幕会闪烁,这是一个比较直接的方法。

注意事项

只在开发阶段启用StrictMode,发布应用或发布版本时一定要禁用。

该模式不能严格监控JNI中的磁盘IO和网络请求。

并不是所有的违例都需要在应用中解决,比如一些IO操作必须在主线程中执行。

总结

以上是边肖介绍的Android的StrictMode的详细说明。希望对你有帮助。如果您有任何问题,请给我留言,边肖将及时回复您。非常感谢您对我们网站的支持!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • windowsandroid手机版下载,windowsandroid安装apk
  • windowsandroid手机版下载,windowsandroid安装apk,WindowsAndroid 安装教程详解
  • android调用webview方法,androidwebview是什么,Android 中 WebView 的基本用法详解
  • android传感器高级编程,Android传感器,Android编程之光线传感器用法详解
  • android.app.Dialog,android自定义dialog对话框,Android开发笔记之-Dialog的使用详解
  • android 图片视频轮播框架,androidlayout轮播图,Android实现炫酷轮播图效果
  • android里的viewpager,安卓自定义view流程,Android自定义引导玩转ViewPager的方法详解
  • android里的viewpager,android viewpager详解
  • android里的viewpager,android viewpager详解,Android自定义超级炫酷的ViewPage指示器
  • android调用webview方法,androidwebview是什么
  • android设置控件宽度,android获取屏幕宽度和高度
  • android设置控件宽度,android获取屏幕宽度和高度,Android中获取控件宽高的4种方法集合
  • android蓝牙开发的基本流程,安卓蓝牙app开发教程
  • android蓝牙开发的基本流程,安卓蓝牙app开发教程,android蓝牙简单开发示例教程
  • android菜单栏,android菜单控件
  • 留言与评论(共有 条评论)
       
    验证码: