Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题

本文主要是介绍Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

StrictMode意思为严格模式,是用来检测程序中违例情况的开发者工具。使用一般是场景是检测主线程中本地磁盘和网络读写等耗时的操作。注意这个StrictMode是在Anroid2.3以后引入的。严格模式主要检测两大问题,一个是线程策略,即TreadPolicy,另一个是VM策略,即VmPolicy。

线程策略(ThreadPolicy)检测的内容有

  • 1、自定义的耗时调用 使用detectCustomSlowCalls()开启
  • 2、磁盘读取操作 使用detectDiskReads()开启
  • 3、磁盘写入操作 使用detectDiskWrites()开启
  • 4、网络操作 使用detectNetwork()开启

虚拟机策略(VmPolicy)检测的内容有

  • 1、Activity泄露 使用detectActivityLeaks()开启
  • 2、未关闭的Closable对象泄露 使用detectLeakedClosableObjects()开启
  • 3、泄露的Sqlite对象 使用detectLeakedSqlLiteObjects()开启
  • 4、检测实例数量 使用setClassInstanceLimit()开启

可以看到线程策略主要与异步处理相关,虚拟机策略主要与内存管理相关。setThreadPolicy()将对当前线程应用该策略。如果不指定检测函数,也可以用detectAll()来替代。penaltyLog()表示将警告输出到LogCat,你也可以使用其他或增加新的惩罚(penalty)函数,例如使用penaltyDeath()的话,一旦StrictMode消息被写到LogCat后应用就会崩溃。另外虚拟机策略(VmPolicy)不能通过一个对话框提供警告。

在线程策略(ThreadPolicy)检测的时候,有几个penalty系列方法。

  • 1、penaltyDeath(),当触发违规条件时,直接Crash掉当前应用程序。
  • 2、penaltyDeathOnNetwork(),当触发网络违规时,Crash掉当前应用程序。
  • 3、penaltyDialog(),触发违规时,显示对违规信息对话框。
  • 4、penaltyFlashScreen(),会造成屏幕闪烁,不过一般的设备可能没有这个功能。

如何使用严格模式

严格模式的开启可以放在Application或者Activity以及其他组件的onCreate方法。为了更好地分析应用中的问题,建议放在Application的onCreate方法中。设置一次就够了。

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll()//开启所有的detectXX系列方法.penaltyDialog()//弹出违规提示框.penaltyLog()//在Logcat中打印违规日志.build());requestDataFromNet();}/*** 请求数据*/private void requestDataFromNet() {URL url;try {url = new URL("http://www.baidu.com");HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.connect();BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));String lines ;StringBuilder sb = new StringBuilder();while ((lines = reader.readLine()) != null) {sb.append(lines);}Log.d("response",sb.toString());} catch (Exception e) {e.printStackTrace();}}
}

比如上面代码运行之后,就会有下面的弹窗出来警告。 

看一下logcat的日志,是在主线程中做了访问网络的操作。

12-19 17:28:54.226 2729-2729/? D/StrictMode: StrictMode policy violation; ~duration=44 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=63 violation=4at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1123)at java.net.InetAddress.lookupHostByName(InetAddress.java:385)at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)at java.net.InetAddress.getAllByName(InetAddress.java:214)at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)at zhangwan.wj.com.myshare.MainActivity.requestDataFromNet(MainActivity.java:35)at zhangwan.wj.com.myshare.MainActivity.onCreate(MainActivity.java:27)at android.app.Activity.performCreate(Activity.java:5104)at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1092)at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2254)at android.app.ActivityThread.access$600(ActivityThread.java:141)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)at android.os.Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:137)at android.app.ActivityThread.main(ActivityThread.java:5069)at java.lang.reflect.Method.invokeNative(Native Method)at java.lang.reflect.Method.invoke(Method.java:511)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)at dalvik.system.NativeStart.main(Native Method)

上面分析了是异步处理相关的例子,现在分析一个内存管相关的例子,比如检测内存泄露检测,用StrickMode怎么搞?

 public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectActivityLeaks()//检测Activity泄露.penaltyLog()//在Logcat中打印违规日志.build());UserManger instance = UserManger.getInstance(this);}}

比如上面的代码UserManger持有了Activity的引用,当反复进入Activity的时候,Activity不能被回收,导致了内存泄露,此时看Logcat。

12-20 09:57:07.626 4787-4787/? E/StrictMode: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1android.os.StrictMode$InstanceCountViolation: class zhangwan.wj.com.myshare.MainActivity; instances=3; limit=1at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

明确告诉我们instances=3,说明泄露了3个MainActivity对象

严格模式除了可以检测Activity的内存泄露之外,还能自定义检测类的对象泄露。这个从从API 11 开始。

public
StrictMode.VmPolicy.Builder setClassInstanceLimit (Class klass, int instanceLimit)

比如,检测UserManger有没有泄露,可以这么写。

StrictMode.setVmPolicy(new VmPolicy.Builder().setClassInstanceLimit(UserManger.class, 1).penaltyLog().build());

在比如detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),资源没有正确关闭时回触发,detectLeakedRegistrationObjects() 用来检查 BroadcastReceiver 或者 ServiceConnection 注册类对象是否被正确释放等。

StrictMode有个更直接的办法,在部分手机上,可以在开发者选项中开启严格模式,开启之后,如果主线程中有执行时间长的操作,屏幕则会闪烁。OKStrictMode比较简单,到此结束!

这篇关于Android性能优化第(七)篇---StrickMode严苛模式检测耗时与内存问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/755140

相关文章

关于@MapperScan和@ComponentScan的使用问题

《关于@MapperScan和@ComponentScan的使用问题》文章介绍了在使用`@MapperScan`和`@ComponentScan`时可能会遇到的包扫描冲突问题,并提供了解决方法,同时,... 目录@MapperScan和@ComponentScan的使用问题报错如下原因解决办法课外拓展总结@

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言