android:StrictMode的使用

来源:互联网 发布:阿里云基础服务平台图 编辑:程序博客网 时间:2024/06/08 13:06

自Android2.3开始就引入了一个名为StrictMode的调试功能,该功能有多种不同的策略,每一种策略又有不同的规则,当开发者违反了某个规则时,则会提醒用户;


StrictMode的策略和规则

目前StrictMode有两种类型的策略可供使用,第一种策略与线程相关,最常用于针对主线程(UI线程)来检测,如果在主线程启用了StrictMode之后,该线程如果执行了磁盘读写或网络访问相关的操作,则会得到提醒;提醒的方式可以选择写入到LogCat中、显示对话框、在屏幕上闪烁显示、写入到DropBox日志文件或者崩溃应用程序;

如下所示的是策略中与线程相关的规则:

Disk Reads —— 磁盘读、Disk Writes 磁盘写、 Network access —— 网络访问、 Custom Slow Code 自定义的运行速度慢的代码分析;

磁盘读写和网络访问都能够很直观的明白其所含义,分别是对磁盘的读写以及网络访问进行监控;而自定义慢代码分析则是仅当访问调用类的时候才触发的,可以通过这种方式去监听运行缓慢的代码;当在主线程中调用时,这些策略规则会进行检测;比如应用正在下载或者解析大量的数据时,可以启用自定义运行速度慢代码来检测;StrictMode可以用于检测发生在应用程序主线程中耗时的磁盘读写、网络访问或函数调用;可以通过StrictMode来对应用进行检测,避免主线程被阻塞的发生以及对程序进行一步的优化;


对于另一种VM策略则重点关注如下规则:

内存泄漏的Activity对象、内存泄漏的SQLite对象、内存泄漏的释放对象;

其中内存泄漏的Activity对象和内存泄漏的SQLite对象都比较好理解,而所谓对关闭对象的检测,主要是去检测那些本该释放的对象,比如应该调用close() 方法的对象;


两种策略的使用:


// 启用磁盘读写、网络访问检测            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()            // 检测磁盘读写            .detectDiskReads()            .detectDiskWrites()            // 检测网络访问            .detectNetwork()            // 提醒方式为输出到LogCat中            .penaltyLog()            .build());

setThreadPolict()方法将在当前线程启用该策略,在后续的操作中将依据ThreadPolict来检测并在必要时发出提醒,代码中指定了检测磁盘读写以及网络访问的检测;如果没有要指定的规则则可以使用detectAll()来代替,datectAll()表示检测当前策略中的所有规则;


除了ThreadPolict之外,StrictMode还有一个VmPolict,VmPolict与ThreadPolict唯一的不同点则是Vmpolict不能使用对话框进行提醒;


// 启用内存泄漏检测            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()            // 各种检测,如无指定的规则可替换为detectAll()            .detectActivityLeaks()            .detectLeakedClosableObjects()            .detectLeakedRegistrationObjects()            .detectLeakedSqlLiteObjects()            // 将提醒输出到LogCat            .penaltyLog()            .penaltyDeath()            .build());

当开启了VmPolict策略后就会进行检测当前程序中是否存在内存泄漏的可能,以及对象是否正确的被释放;对于StrictMode策略的启用可以放在Activity类中的onCreate方法中;如下


    @Override    public void onCreate(Bundle savedInstanceState) {    // 开启策略检测        super.onCreate(savedInstanceState);    }



有效的控制StrictMode是否启用

StrictMode作为一个调试功能,也就意味着它仅仅是在开发测试阶段才需要的,当正常发布应用程序时则不再需要该调试功能了;最简单的方式就是将StrictMode相关的代码删除,但这样会使得很难进行对它进行开;我们可以定义一个布尔型的标记,通过该布尔型的标记来决定是否开启StrictMode策略;


除此之外我们可以利用清单文件中的android:debuggable标签,当使用Eclipse开发时,ADT会自动设置debuggable的属性,将工程从Eclipse部署到模拟器或直接部署到设备时,ADT会将属性设置为true,而如果导出工程创建版本时,ADT会将它设置为false;需要注意的时如果手动设置了debuggable的属性后ADT则不会对它进行修改;通过这个特征我们可以在代码中动态的决定是否开启StrictMode策略,代码如下:


ApplicationInfo appInfo = context.getApplicationInfo();        int appFlags = appInfo.flags;        if((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {        // 在此进行StrictMode的开启        }

忽略某些规则

应该说大部分由StrictMode提示的警告都应该去遵守,但有时也不是所有的信息都表示程序存在错误,比如在应用程序的主线程快速读写磁盘其实并不会对应用的性能产生太大的影响,又或者在调试程序阶段有一些调试代码违反了设定的规则,这时则可以忽略掉这些规则;

忽略规则有两种方式,一种是简单的将代码中把StrictMode的代码注释掉,而另外一种比较好的方式是,在需要忽略的时候和地方,增加相应的代码去让系统停止使用这些规则去检测,等开发者认为有必要检测时,再重新应用这些规则,代码如下:

        // 获取到原来的检测模式        StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();        // 重新设置检测的模式        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)        // 允许读写        .permitDiskWrites()        .permitDiskReads()        .build());                // TODO 执行读写操作                // 再次设置回原先的检测模式        StrictMode.setThreadPolicy(old);








原创粉丝点击