Android内置性能监测器StrictMode的使用

StrictMode是一个开发者工具,它可以帮助我们监测到在大量代码中运行在主线程中我们不容易发现的耗时操作,这些耗时操作显然是放错了位置的,他们应该在工作线程中运行,如果我们自己一行一行去发现这种错误,代码少的话还可以,代码一多,这显然是不可能做到的事情。

我们的UI有时候会有卡顿,这也是因为我们不小心在主线程UI中放置了耗时的操作,比如我们有一个listview,滑动起来很卡顿,那很有可能是我们把一些磁盘读写操作或者网络操作放到的主线程中去了,UI线程是用来展示数据和动画的,将磁盘和网络操作放到其他线程会使得UI线程运行的更加流畅,响应更加及时,而且还可以避免ANR。

我们在Application或者Activity中的onCreate()方法中加入如下代码,就可以进行监测了

public void onCreate() {
     //定义一个开关,在测试版本中为true  在正式版本中为false
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 //监测磁盘读
                 .detectDiskReads()
                 //监测磁盘写
                 .detectDiskWrites()
                 //监测网络
                 .detectNetwork()
                 //.detectAll()   监测所有
                 //打印日志
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 //监测数据库对象泄露
                 .detectLeakedSqlLiteObjects()
                 //监测可关闭的对象泄露
                 .detectLeakedClosableObjects()
                 //打印日志
                 .penaltyLog()
                 //在最后调用,关闭监测器进程,但是不影响log打印
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }

接下来我们来测试一下,我有一个项目,需要用到数据库,我将数据库的插入写在了UI线程中,我们来监测一下,看看打印的log

public class MainActivity extends Activity {
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private PersonDao personDao;
    //定义一个开关,在我们发布正式版本的时候,要记得改为false。在测试版本的时候,改为true
    private static final boolean DEVELOPER = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //如果是测试版本的话
        if (DEVELOPER) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            //detectAll()是监测所有,包括读磁盘 写磁盘 网络等
            .detectAll()
            //将监测信息打印到logcat中
            .penaltyLog()
            .build());
        }
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDaoSession = MyApplication.getDaoSession(getApplicationContext());
        personDao = mDaoSession.getPersonDao();
        personDao.deleteAll();
        Person p1 = new Person(1l, "zhangyi","1");
        Person p2 = new Person(2l, "zhangyi","2");
        Person p3 = new Person(3l, "zhangsan","5");
        Person p4 = new Person(4l, "zhangyi","4");
        Person p5 = new Person(5l, "zhangwu","1");
        personDao.insert(p1);
        personDao.insert(p2);
        personDao.insert(p3);
        personDao.insert(p4);
        personDao.insert(p5);
        QueryBuilder<Person> queryBuilder = personDao.queryBuilder();
        List<Person> list = queryBuilder.where(Properties.Id.ge(2l), Properties.Name.eq("zhangyi")).list();
    }

我们看第一行,这个耗时操作耗时302ms,violation=1说明有一个耗时操作在主线程中运行了,耗费了302ms的时间,这无疑会造成UI的卡顿。而且通过分析下面的信息我们可以得知,这个耗时操作是写磁盘操作。所以通过StrictMode可以非常清楚的发现我们项目中潜在的性能问题。

那么,现在我将数据库操作放到一个工作线程中去执行

public class MainActivity extends Activity {
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private PersonDao personDao;
    //定义一个开关,在我们发布正式版本的时候,要记得改为false。在测试版本的时候,改为true
    private static final boolean DEVELOPER = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //如果是测试版本的话
        if (DEVELOPER) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
            //detectAll()是监测所有,包括读磁盘 写磁盘 网络等
            .detectAll()
            //将监测信息打印到logcat中
            .penaltyLog()
            .build());
        }
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //开启一个线程去执行数据库操作
        new Thread(new Runnable() {

            @Override
            public void run() {
                mDaoSession = MyApplication.getDaoSession(getApplicationContext());
                personDao = mDaoSession.getPersonDao();
                personDao.deleteAll();
                Person p1 = new Person(1l, "zhangyi","1");
                Person p2 = new Person(2l, "zhangyi","2");
                Person p3 = new Person(3l, "zhangsan","5");
                Person p4 = new Person(4l, "zhangyi","4");
                Person p5 = new Person(5l, "zhangwu","1");
                personDao.insert(p1);
                personDao.insert(p2);
                personDao.insert(p3);
                personDao.insert(p4);
                personDao.insert(p5);
                QueryBuilder<Person> queryBuilder = personDao.queryBuilder();
                List<Person> list = queryBuilder.where(Properties.Id.ge(2l), Properties.Name.eq("zhangyi")).list();
            }
        }).start();
        ;
    }

运行后我们发现logcat中没有打印任何关于StrictMode的警告信息。说明我们的UI线程非常流畅

因此StrictMode是一个非常有用的工具,使用这个工具我们可以找到并修复一些微小的性能问题,像对象泄露等非常难发现的问题。所以,你的项目中使用StrictMode了吗?

版权声明:欢迎转载,转载请注明出处http://blog.csdn.net/nugongahou110

时间: 2024-08-29 15:38:11

Android内置性能监测器StrictMode的使用的相关文章

Android内置颜色及其它颜色RGB对照表

参考:http://blog.csdn.net/feiyangxiaomi/article/details/38338305 我们在平时开发时经常要用到各种颜色,有了下面这两张表,妈妈再也不用担心你的配色问题了. 一:内置颜色: public static final int BLACK Added in API level 1 Constant Value: -16777216 (0xff000000)        public static final int BLUE Added in 

写一个android内置android程序

当我们编译完毕android源代码之后,就须要对他做点什么事情,我如今正在看老罗的"Android源代码情景分析"一书.在这里主要是记录一些书中没有说清楚的地方. 相同.我们创建一个HelloWorld程序,以下看一下我的文件夹结构. 然后我们就像平时开发android程序一样.在第一个界面中放置一个 Hello World字符串,然后在自己的手机中測试一下.执行成功.好了.后面的工作比較重要. 在这里记录一下Android.mk里面的内容,这个是必须要有的.由于mmm编译的话.须要找

mtk android内置nginx服务器的方法

因为项目需要,需要在一台android 6572的方法上内置nginx. 首先,使用arm-linux-gcc编译nginx. 我们先手动安装nginx,看看是否可行,如果可行,然后再在代码中间集成. 1, 现在android上面建立gnulib的环境 先把相关库push到android的/system/lib/上 ld-linux.so.3 libc.so.6 libnsl.so.1 libnss_compat.so.2 libnss_dns.so.2 libnss_files.so.2 li

Android 学习心得(2)——Android内置数据库SQLite

一.简介: Android有一个内置数据库SQLite,它是一种轻型数据库,它有五种数据类型:NULL(空型).BLOB(二进制).INTEGER(整型).REAL(浮点型).TEXT(字符串文本),虽然有着五种数据之分,但是在内部SQLite存储数据是无类型的,也就是说你可以在integer中存入char数据之类的.  二.要点: INTEGER PRIMARY KEY中只能存放64位整数 在编写CREATE TABLE时候可以省略字段后面的数据类型 SQLite中可以解析大部分标准SQL语句

【Android】16.5 Android内置的系统服务

分类:C#.Android.VS2015: 创建日期:2016-03-01 一.简介 实际上,在Android.Content.Context类中,Android已经提供了多种类型的系统服务,这些服务都以静态的形式通过Android.Content.ContextWrapper类提供的GetSystemService()方法让开发人员调用. 在Activity及其子类中,可直接调用GetSystemService方法.例如: public class MainActivity : Activit

Android内置下拉刷新组件SwipeRefreshLayout

也许下拉刷新之前,你可能会使用一些第三方的开源库,例如PullToRefresh, ActionBar-PullToRefresh等待,但现在有的正式组成部分---SwipeRefreshLayout,SwipeRefreshLayout是Google在support v4 19.1版本号的library更新的一个下拉刷新组件,使用起来非常方便,能够非常方便的实现Google Now的刷新效果. 使用官方自带的控件能够保证通用性以及风格.SwipeRefreshLayout是继承ViewGrou

【Android】9.2 内置行视图的分类和呈现效果

分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 Android内置了很多行视图模板,在应用程序中可直接使用这些内置的视图来呈现列表项. 要在ListView中使用内置的行视图呈现列表项,只需要通过Android.Resource.Layout类的属性指定资源的ID即可.例如: public class MainActivity : Activity { -- protected override void OnCreate(Bundle bundle) {

Android通过意图使用内置的音频播放器

如果实现一个音频文件的播放,那么在应用程序中提供播放音频文件功能的最简单的方式是利用内置的"Music(音乐)"应用程序的功能--即使用系统自带的或已安装好的音乐播放器来播放指定的音频文件. 本例比较简单,下面直接给出源代码: 布局文件activity_main: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http:/

下载PHPDroid: 基于WebView和PHP内置HTTP服务器开发Android应用

基于Android上的PHP(比如我打包的PHPDroid),寥寥几行PHP代码,就能实现一个支持无线局域网用浏览器访问的Android手机的Shell,用于执行命令和PHP代码.       个人在Ubuntu上使用交叉编译工具链  arm-none-linux-gnueabi 或 musl-cross-compilers(推荐)  按照  DroidPHP 的教程 cross_compile_php.txt 这是我使用musl-cross-compilers交叉编译Android版PHP7的