前言

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

检测卡顿常用工具

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. LeetCode57. 插入区间

    对于新插入的区间newInterval,原区间列表intervals可以分为三个部分: 左边与newInterval不重合的区间,这些区间直接加入结果数组中: 中间与newInterval重合的区间, ...

  2. 猿灯塔:疫情冲击,去体验远程面试被怼10分钟,今年Java开发找工作真难

    网行业,美团王兴曾说:“2019年可能会是过去十年里最差的一年,却是未来十年里最好的一年”.没想到预言竟然快成真了? 年前很多企业一波裁员,2020年又受疫情影响,延长了假期,各大企业复工时间拉长,招 ...

  3. 基于SpringBoot AOP面向切面编程实现Redis分布式锁

    基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式 ...

  4. 在Linux上部署jmeter

    一.服务器安装jmeter 1.将安装文件上传到Linux服务器 通过xshell文件上传工具,将文件 “apache-jmeter-5.1.1.tgz”上传 2.在服务器解压缩“apache-jme ...

  5. .NET WEB API关键过程 思维导图

    背景说明 近期在去面试的过程中,被问及有关WEB API的一些特性,一时竟不知该如何回答,故根据自己已知的知识,加上网上搜索的,详细列举了一下,期望对WEB API有一个比较开阔和全面的认知. 关键要 ...

  6. CCNA-Part5 - 传输层 ,TCP 为什么是三次握手?

    传输层 传输层主要的作用就是建立端到端的连接.比如电脑的微信的通信,就需要跨越多个网络设备(交换机和录取)再和微信的服务器建立连接. 传输层需要具有以下的特点: 会话的多复用:如电脑上开启的多个应用, ...

  7. SpringBoot执行定时任务@Scheduled

    SpringBoot执行定时任务@Scheduled 在做项目时,需要一个定时任务来接收数据存入数据库,后端再写一个接口来提供该该数据的最新的那一条. 数据保持最新:设计字段sign的值(0,1)来设 ...

  8. redis(十七):Redis 安装,部署(WINDOWS环境下)

    1.下载Redis安装文件, 我选择的是 3.0.504 版本,有zip或msi可供下载.   2.解压缩后,打开安装目录 双击redis-server.exe启动redis服务器,双击redis-c ...

  9. 《你还在写sql语句吗?》人生苦短,进入MybatisPlus的丝滑体验

    一.发展历程 依稀记得大学期间,类中写sql语句的日子,一个sql语句占据了大部分时间,到后来hibernate的出现算是解决了这一痛点.工作 后,我们又接触到了mybatis这样的框架,瞬间感觉这个 ...

  10. 模板方法模式(c++实现)

    外观模式 目录 外观模式 模式定义 模式动机 UML类图 源码实现 优点 缺点 模式定义 模板方法模式(Facade),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变 ...