前言

无论是启动,内存,布局等等这些优化,最终的目的就是为了应用不卡顿。应用的体验性好坏,最直观的表现就是应用的流畅程度,用户不知道什么启动优化,内存不足,等等,应用卡顿,那么这个应用就不行,被卸载的概率非常大。所以说为了保证用户留存率,卡顿优化是非常非常的重要。在这篇文章,咱们不讨论是什么原因造成卡顿,其实在前面写的性能优化文章中,都是造成卡顿的原因,需要需要做好卡顿优化,最好从头开始一步一步来处理。今天我们主要是介绍一些针对卡顿检测的一些工具使用。

检测卡顿常用工具

Systrace

Systrace这个工具在《布局优化》一章节中已经介绍过了,这里就不在赘述。地址:https://www.cnblogs.com/huangjialin/p/13353541.html

StrictMode的使用

StrictMode,严苛模式。StrictMode是在Android开发过程中不可缺少的性能检测工具,它能够检测出在开发过程中不合理的代码块,非常方便。

策略分类

StrictMode分为线程策略(ThreadPolicy)和虚拟机策略(VmPolicy)

使用方式
 //开启Thread策略模式
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectNetwork()//监测主线程使用网络io
// .detectCustomSlowCalls()//监测自定义运行缓慢函数
// .detectDiskReads() // 检测在UI线程读磁盘操作
// .detectDiskWrites() // 检测在UI线程写磁盘操作
.detectAll()
.penaltyLog() //写入日志
.penaltyDialog()//监测到上述状况时弹出对话框
.build()); //开启VM策略模式
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
// .detectLeakedSqlLiteObjects()//监测sqlite泄露
// .detectLeakedClosableObjects()//监测没有关闭IO对象
// .setClassInstanceLimit(MainActivity.class, 1) // 设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露
// .detectActivityLeaks()
.detectAll()
.penaltyLog()//写入日志
.build());

上面基本都注释好了,这里就不在一一说明了。如果我们在开发过程中,能够通过StrictMode这个工具类来规避掉这些问题,那么将会大大的减少很多性能相关的问题。

BlockCanary使用

我们先看看怎么使用,然后在看BlockCanary

依赖

debugImplementation 'com.github.bzcoder:blockcanarycompat-android:0.0.4'

在application中

BlockCanary.install(mContext, appBlockCanaryContext).start();

appBlockCanaryContext类

/**
* BlockCanary配置的各种信息
*/
public class AppBlockCanaryContext extends BlockCanaryContext { /**
* Implement in your project.
*
* @return Qualifier which can specify this installation, like version + flavor.
*/
public String provideQualifier() {
return "unknown";
} /**
* Implement in your project.
*
* @return user id
*/
public String provideUid() {
return "uid";
} /**
* Network type
*
* @return {@link String} like 2G, 3G, 4G, wifi, etc.
*/
public String provideNetworkType() {
return "unknown";
} /**
* Config monitor duration, after this time BlockCanary will stop, use
* with {@code BlockCanary}'s isMonitorDurationEnd
*
* @return monitor last duration (in hour)
*/
public int provideMonitorDuration() {
return -1;
} /**
* Config block threshold (in millis), dispatch over this duration is regarded as a BLOCK. You may set it
* from performance of device.
*
* @return threshold in mills
*/
public int provideBlockThreshold() {
return 500;
} /**
* Thread stack dump interval, use when block happens, BlockCanary will dump on main thread
* stack according to current sample cycle.
* <p>
* Because the implementation mechanism of Looper, real dump interval would be longer than
* the period specified here (especially when cpu is busier).
* </p>
*
* @return dump interval (in millis)
*/
public int provideDumpInterval() {
return provideBlockThreshold();
} /**
* Path to save log, like "/blockcanary/", will save to sdcard if can.
*
* @return path of log files
*/
public String providePath() {
return "/blockcanary/";
} /**
* If need notification to notice block.
*
* @return true if need, else if not need.
*/
public boolean displayNotification() {
return true;
} /**
* Implement in your project, bundle files into a zip file.
*
* @param src files before compress
* @param dest files compressed
* @return true if compression is successful
*/
public boolean zip(File[] src, File dest) {
return false;
} /**
* Implement in your project, bundled log files.
*
* @param zippedFile zipped file
*/
public void upload(File zippedFile) {
throw new UnsupportedOperationException();
} /**
* Packages that developer concern, by default it uses process name,
* put high priority one in pre-order.
*
* @return null if simply concern only package with process name.
*/
public List<String> concernPackages() {
return null;
} /**
* Filter stack without any in concern package, used with @{code concernPackages}.
*
* @return true if filter, false it not.
*/
public boolean filterNonConcernStack() {
return false;
} /**
* Provide white list, entry in white list will not be shown in ui list.
*
* @return return null if you don't need white-list filter.
*/
public List<String> provideWhiteList() {
LinkedList<String> whiteList = new LinkedList<>();
whiteList.add("org.chromium");
return whiteList;
} /**
* Whether to delete files whose stack is in white list, used with white-list.
*
* @return true if delete, false it not.
*/
public boolean deleteFilesInWhiteList() {
return true;
} /**
* Block interceptor, developer may provide their own actions.
*/
public void onBlock(Context context, BlockInfo blockInfo) {
Log.i("lz","blockInfo "+blockInfo.toString());
}
}

就是这么简单,一旦发生卡顿,那么将会以通知的形式在通知栏中显示出对应的堆栈信息(和leakcanary类似,但是两者没有任何关系)。或者在

SD卡中的blockcanary文件夹中生成对应的log日志

那么,问题来了BlockCanary是怎么检测卡顿的呢?大家注意AppBlockCanaryContext类中有一个provideBlockThreshold()方法,return了一个500ms。我们知道Android中消息的分发处理都是通过handler来的,handler中有一个looper对象,looper对象中有一个loop方法,看一下源码

...

 for (;;) {
Message msg = queue.next(); // might block
...//省略若干
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
} ...//省略若干 try {
msg.target.dispatchMessage(msg);
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...//省略若干 if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
} ...//省略若干
} ...

应用中的所有事件都是通过dispatchMessage这个方法来进行处理,那么是不是说dispatchMessage执行的时间就是某个事件执行的时间。如果这个时间大于我们在provideBlockThreshold()定义的时间,我们就认为发送了卡顿了,需要优化,就会获取到对应的堆栈信息保存起来并提示。

ANR-WatchDog介绍

发生卡顿,严重时很容易导致anr,我们知道发生anr的情况基本上就是以下几种情况

1、触摸事件在5s没有得到响应。

2、Bradcast 是10s,后台广播是60s

3、service:前台service 20s 后台service 200s

用户在使用应用时,出现ANR,那么体验将会是非常非常差,现在很多手机厂商为了用户体验,去掉了这个ANR弹框,但是还是会一直卡在这里。

ANR-WatchDog 使用

添加依赖

implementation 'com.github.anrwatchdog:anrwatchdog:1.3.0'

在application中的onCreate()方法

new ANRWatchDog().setIgnoreDebugger(true).start();

setIgnoreDebugger 是指忽略点断点的情况

当然如果这样设置的话,一旦出现ANR,那么ANR-Watchdog是会将应用杀死的,如果不想杀死应用那么需要设置一个监听

new ANRWatchDog().setANRListener(new ANRWatchDog.ANRListener() {
@Override
public void onAppNotResponding(ANRError error) {
// Handle the error. For example, log it to HockeyApp: }
}).start();

ANR-WatchDog 原理

我用自己的话来总结一下原理:前面我们说了所有的消息都是通过handler中的dispatchMessage方法进行分发的,而ANR-WatchDog 原理就是通过dispatchMessage的时间长度来判断是否出现anr的,过程大概是这样的:ANR-WatchDog 开启一个监控线程,并向主线程发一个消息,然后自己休眠5s,5s后看主线程有没有处理这个消息,如果处理了,那么继续发送,进入一下次检查。如果没有处理,说明主线程发生了阻塞,收集对应的anr信息。

Lancet的介绍

前面写的几篇性能优化文章基本都介绍有对应的hook框架,这里再介绍一个AOP框架---Lancet,这几个框架的比对,后面会再开一篇。这里先看看怎么使用。Lancet是一个轻量级Android AOP框架,特点:

1、编译速度快,并且支持增量编译

2、简洁的API,几行代码完成注入需求

3、没有任何多余代码插入apk

4、支持用于SDK,可以在SDK编写注入代码来修改依赖SDK的APP

使用方式

在根目录的build.gradle

dependencies{

classpath 'me.ele:lancet-plugin:1.0.5'

}

在APP目录的build.gradle

apply plugin: 'me.ele.lancet'

dependencies {

provided 'me.ele:lancet-base:1.0.5'

}

开一个类aaaa.java

@Proxy("i")

@TargetClass("android.util.Log")

public static int anyName(String tag, String msg){

msg = msg + "lancet";

return (int) Origin.call();

}

这样,就完成了,当我们通过Log.i("lancet","你好“);来打印日志的时候,输出的文本先被Lancet出来后,在输出。"你好,lancet"

常见卡顿问题解决方案

1、内存抖动的问题,GC过于频繁

2、方法太耗时了(CPU占用)

3、布局过于复杂,渲染速度慢

....

Android性能优化----卡顿优化的更多相关文章

  1. android中app卡顿优化问题

     所谓app卡顿原因就是在运行时出现了丢帧,还可能是UI线程被阻塞.首先来一下丢帧现象,android每16ms会对界面进行一次渲染,如果app的绘制.计算等超过了16ms那么只能等下一个16ms才能 ...

  2. Android TextView setText卡顿问题

    TextView 是经常使用控件之中的一个,最经常使用的方法是setText()  . 可是 我们在显示大量的文本的时候,使用setText还是会有一些性能的问题. 这篇文章 关于TextView的s ...

  3. android TextView SetText卡顿原因

    [android TextView SetText卡顿原因] 不要用wrap_content即可. 参考:http://blog.csdn.net/self_study/article/details ...

  4. Android 界面滑动卡顿分析与解决方案(入门)

    Android 界面滑动卡顿分析与解决方案(入门) 导致Android界面滑动卡顿主要有两个原因: 1.UI线程(main)有耗时操作 2.视图渲染时间过长,导致卡顿 目前只讲第1点,第二点相对比较复 ...

  5. Android 卡顿优化 2 渲染优化

    1.概述 2015年初google发布了Android性能优化典范,发了16个小视频供大家欣赏,当时我也将其下载,通过微信公众号给大家推送了百度云的下载地址(地址在文末,ps:欢迎大家订阅公众号),那 ...

  6. Android 卡顿优化 1 卡顿解析

    1, 感知卡顿 用户对卡顿的感知, 主要来源于界面的刷新. 而界面的性能主要是依赖于设备的UI渲染性能. 如果我们的UI设计过于复杂, 或是实现不够好, 设备又不给力, 界面就会像卡住了一样, 给用户 ...

  7. Android 卡顿优化 3 布局优化 工具 Hierarchy Viewer

    欲善其事, 先利其器. 分析布局, 就不得不用到Hierarchy Viewer了. 本文工具使用皆以GithubApp的详情界面RepoDetailActivity为例说明. 为了不影响阅读体验, ...

  8. Android 布局渲染流程与卡顿优化

    文章内容概要 一.手机界面UI渲染显示流程 二.16ms原则 三.造成卡顿的原因 四.过度绘制介绍.检测工具.如何避免造成过度绘制造成的卡顿 一.手机界面UI渲染显示流程 大家都知道CPU(中央处理器 ...

  9. GC 卡顿 优化 三色标记优势

    小结: 1. 三色标记的一个明显好处是能够让用户程序和 mark 并发的进行 Go GC 卡顿由秒级降到毫秒级以下:到底做了哪些优化? https://mp.weixin.qq.com/s/2BMGG ...

随机推荐

  1. plsql截取字符串字段中的某个字符段

    截取字符串 字符串s=" hello world  ! (name) " 如果要截取括号中的字符串可以采取如下方法. select substr(s,instr(s,'(')+1, ...

  2. codeforce 796C - Bank Hacking(无根树+思维)

    题目 Although Inzane successfully found his beloved bone, Zane, his owner, has yet to return. To searc ...

  3. 关于WebServices的调用

    1.使用soapui测试接口是否能通    具体操作步骤请查看:https://www.cnblogs.com/BINDAI/p/13201513.html Soapui请求结果集 2.获得soapu ...

  4. vs2017+opencv3.4.0的配置方法

    1.尝试了这个博客的方法: https://blog.csdn.net/u014574279/article/details/50909425/ 结果: 无法打开文件“opencv_ml2410d.l ...

  5. 「MoreThanJava」Day 3:构建程序逻辑的方法

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  6. MRCTF 2020-“TiKi小组”

    题目状态: OPEN - 正在试图解这道题CLOSED - 这道题还没有打开SOLVED - 解决了!鼓掌撒花! 赛事信息 Flag格式:MRCTF{}起止时间:2020-03-27 18:00:00 ...

  7. Pandas基础知识图谱

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片.该图谱只 ...

  8. 机器学习实战基础(二十一):sklearn中的降维算法PCA和SVD(二) PCA与SVD 之 降维究竟是怎样实现

    简述 在降维过程中,我们会减少特征的数量,这意味着删除数据,数据量变少则表示模型可以获取的信息会变少,模型的表现可能会因此受影响.同时,在高维数据中,必然有一些特征是不带有有效的信息的(比如噪音),或 ...

  9. 00-Windows系统MySQL数据库的安装

    1.数据库安装 官网下载MySQL数据库. 下载安装包后解压缩到相关目录,我解压缩到:D:\360极速浏览器下载\mysql-8.0.19-winx64. 打开刚刚解压的文件夹 D:\360极速浏览器 ...

  10. Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览

    当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...