Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >卡顿优化

卡顿优化

作者头像
Yif
发布于 2020-04-23 09:40:54
发布于 2020-04-23 09:40:54
1.9K00
代码可运行
举报
文章被收录于专栏:Android 进阶Android 进阶
运行总次数:0
代码可运行

耗时任务

StrictMode

帮助开发者检查代码不规范问题 严苛模式:Android 提供的一种运行检查机制 方便强大,容易被忽视,包含线程策略与虚拟机检测策略

线程策略

  1. 自定义耗时调用:detectCustomSlowCalls()
  2. 磁盘读取策略:detectDiskReads()
  3. 网络操作:detectNetwork()

虚拟机策略

  1. Activity泄漏:detectActivityLeaks()
  2. Sqlite泄漏:detectLeakedSqlitebjects()
  3. 检测实例数量:setClassInstanceLimit()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
通过日志进行输出不规范的信息,在日志输出窗口中使用StrictMode进行过滤输出的信息
//在release版本中不建议开启严格模式
    private boolean DEV_MODE = true;
 
    /**
     * StrictMode 用来检测代码规范问题,有两种测量,一种是线程策略,一种是虚拟机策略
     */
    private void initStrictMode() {
        if (DEV_MODE) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectCustomSlowCalls()//检测执行缓慢的代码或者潜在的缓慢代码
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyDialog()//弹窗违规提示框
                    .penaltyLog()//进行违规日志打印
                    .penaltyFlashScreen()
                    .build());
 
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .detectActivityLeaks()//activity 泄漏
                    .detectLeakedClosableObjects()//未关闭的closeable对象泄漏
                    .detectLeakedSqlLiteObjects()//泄漏SQlite对象
                    .penaltyLog()
                    // .penaltyDeath()//使用严格模式,系统会做出相应的反应,比如打印日志,弹出对话框,以及崩溃,这里进行崩溃操作
                    .build());
        }
    }
 

注意

  1. 在线上环境即Release版本不建议开启严格模式。
  2. 严格模式无法监控JNI中的磁盘IO和网络请求。
  3. 应用中并非需要解决全部的违例情况,比如有些IO操作必须在主线程中进行(Android中io操作在主线程中还是很常见的,比如sp的读写啊,从文件中读取图片啊,缓存啊之类的,并不是都是异步的,只要是不太耗时的就行,但是android中从3.0后就不允许UI线程中进行联网操作了,所以联网是必须独立了)。

数据少量且快速的IO操作是可以放在UI线程的,比如说少量的文件数据读取或者是写入之类的。。 但是如果涉及到数据量较大或者速度较慢的IO操作比如网络请求或者是蓝牙通信,避免放在UI线程中,这会阻塞UI线程,严重的时候甚至会导致app直接闪退报错。。 建议这些耗时的IO操作都放入到新开辟的线程中进行。 UI线程最好只需要负责UI界面的显示更新之类的操作。

Android 监控组件 AndroidPerformanceMonitor

implementation 'com.github.markzhai:blockcanary-android:1.5.0'

AndroidPerformanceMonitor 是一个检测卡顿的开源库,前身是BlockCanary,更前身则是LeakCanary。而其使用与LeakCanary也比较相似,可以自主设置卡顿检测时间,检测到的卡顿同样是以Notification展示,在使用体验上也相当类似,与LeakCanary可以说是孪生兄弟。 原理: 利用了Looper.loop()中每个Message被分发前后的Log打印,而我们设置自己的Printer就可以根据Log的不同的处理: - Message分发前,使用HandlerThread延时发送一个Runnable,这个时间可自己设置; - Message在规定的时间内完成分发,则会取消掉这个Runnable; - Message没有在规定的时间内(实际上是规定时间的0.8)完成分发,那这个Runnable就会被执行,可以获取到当前的堆栈信息;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
    logging.println(">>>>> Dispatching to " + msg.target + " " +
            msg.callback + ": " + msg.what);
}
 
msg.target.dispatchMessage(msg);
 
if (logging != null) {
    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
 
  1. 非侵入式
  2. 方便精准,定位到某一行代码

初始化操作:BlockCanary.install(this, new AppBlockCanaryContext()).start();

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * BlockCanary配置的各种信息
 */
public class AppBlockCanaryContext extends BlockCanaryContext {
 
    /**
     * Implement in your project.
     *
     * @return Qualifier which can specify this installation, like version + flavor.
     */
    @Override
    public String provideQualifier() {
        return "unknown";
    }
 
    /**
     * Implement in your project.
     *
     * @return user id
     */
    @Override
    public String provideUid() {
        return "uid";
    }
 
    /**
     * Network type
     *
     * @return {@link String} like 2G, 3G, 4G, wifi, etc.
     */
    @Override
    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)
     */
    @Override
    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
     */
    @Override
    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)
     */
    @Override
    public int provideDumpInterval() {
        return provideBlockThreshold();
    }
 
    /**
     * Path to save log, like "/blockcanary/", will save to sdcard if can.
     *
     * @return path of log files
     */
    @Override
    public String providePath() {
        return "/blockcanary/";
    }
 
    /**
     * If need notification to notice block.
     *
     * @return true if need, else if not need.
     */
    @Override
    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
     */
    @Override
    public boolean zip(File[] src, File dest) {
        return false;
    }
 
    /**
     * Implement in your project, bundled log files.
     *
     * @param zippedFile zipped file
     */
    @Override
    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.
     */
    @Override
    public List<String> concernPackages() {
        return null;
    }
 
    /**
     * Filter stack without any in concern package, used with @{code concernPackages}.
     *
     * @return true if filter, false it not.
     */
    @Override
    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.
     */
    @Override
    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.
     */
    @Override
    public boolean deleteFilesInWhiteList() {
        return true;
    }
 
    /**
     * Block interceptor, developer may provide their own actions.
     */
    @Override
    public void onBlock(Context context, BlockInfo blockInfo) {
        Log.i("lz","blockInfo "+blockInfo.toString());
    }
}
 

ANR

AMS让应用组件做的操作,没有在规定的时间内完成,就会弹出这个AppNotRespondingDialog弹框告诉该应用未响应。 1. KeyDispacthTimeOut 5s 2. BroadcastTimeout 前台10s, 后台60s 3. ServiceTimeout 前台20s,后台200s 在源码中appNotRespondingmUIHandler通过发送消息弹出一个DialogAppNotRespondingDialog,这里的mUIHandler不是systemServer的主线程,而是子线程

Service超时

realStartServiceLocked中进行启动service,如果应用没有在规定时间内启动服务,就会触发一个超时机制,scheduleServiceTimeoutLocked,就会触发serviceTimeout,弹出AppNotRespondingDialog。如果service正常启动完成就会在handleCreateService中调用AMS的serviceDoneExecutingLocked中移除超时消息

ANR 执行流程

  1. 发送ANR
  2. 进程接收异常终止信号,开始写入进程ANR信息
  3. 弹出ANR提示框(Room表现不一,有些手机厂商会把提示框给去掉)

ANR 解决方式

adb pull data/anr/traces.txt存储路径,然后分析CPU、IO及锁

ANR 测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 //给主线程造成卡顿,在子线程中获取锁,并让主线中等待20s,在让它获取锁
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (MainActivity.this){
                    try {
                        Thread.sleep(20000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
 //申请这把锁
        synchronized (MainActivity.this){
            LogUtils.i("");
        }
 

ANR 监控

  1. 通过FileObserver监控文件变化,高版本权限问题
  2. 使用ANR-WatchDog

ANR-WatchDog

非侵入式ANR检测组件 https://github.com/SalomonBrys/ANR-WatchDog 使用:new ANRWatchDog().start();

原理

ANR-WatchDog同样是一个检测卡顿的检测库,与AndroidPerformanceMonitor不一样的是它的原理相对简单: 原理是开启一个线程,持续循环不断的往UI线程中Post一个Runnable(修改一个数的大小),然后在规定时间之后检测这个Runnable是否被执行(数的大小有没有 被修改过来)。没有被执行的话说明主线程执行上一个Message超时,然后获取当前堆栈信息; ANR-WatchDog的原理更加简单,但是根据使用情况来看准确性不及AndroidPerformanceMonitor高,而且可设置的配置不如AndroidPerformanceMonitor丰富;

AndroidPerformanceMonitor与 ANR-WatchDog 区别
  • AndroidPerformanceMonitor:监控Msg
  • ANR-WatchDog:看最终结果
  • 前者适合监控卡顿,后者适合补充ANR监控
ANR-WatchDog优缺点

优点 1. 兼容性好,各个机型版本通用 2. 无需修改APP逻辑代码,非侵入式 3. 逻辑简单,性能影响不大

缺点 无法保证能捕捉所有ANR,对阈值的设置直接影响捕获概率

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020年4月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android性能优化(六)之卡顿那些事
对普通用户而言,类如内存占用高、耗流量、耗电量等性能问题可能不会轻易发现,但是卡顿问题用户一定会立马直观的感受到。本文就带你一览卡顿的发生、检测、及优化。
用户2898788
2018/08/21
1.2K0
Android性能优化(六)之卡顿那些事
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)
运行程序,等到程序ANR或崩溃, 在Terminal使用刚刚提到的命令,导出ANR的信息文件:
凌川江雪
2020/04/09
5.4K2
Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)
Android卡顿优化 | 自动化卡顿检测方案与优化(AndroidPerformanceMonitor / BlockCanary)
当然,我们可以在logcat中定位关键词blockInfo, 看到同样的详细的信息:
凌川江雪
2020/04/09
2.7K0
Android卡顿优化 | 自动化卡顿检测方案与优化(AndroidPerformanceMonitor / BlockCanary)
Android内存泄露和ANR
内存泄漏(Memory Leak)是指程序在运行过程中,由于疏忽或错误未能释放不再使用的内存,导致这部分内存无法被回收,最终可能引发应用卡顿、崩溃或系统性能下降。
进击的阿斌
2025/02/13
6340
微信Android客户端的卡顿监控方案
文章开始,先聊一聊卡顿与ANR的关系:产生卡顿的根本原因是UI线程不能够及时的进行渲染,导致UI的反馈不能按照用户的预期,连续、一致的呈现。产生卡顿的原因多种多样,很难一一列举,而ANR是Google人为规定的概念,产生ANR的原因最多也只有四个。 一方面,两者息息相关,事实上,长时间的UI卡顿是导致ANR最常见的原因;但另一方面,从原理上来看,两者既不充分也不必要,是两个维度的概念。 而市面上的一些卡顿监控工具,经常被拿来监控ANR(卡顿阈值设置为5秒),这其实很不严谨:首先,5秒只是发生ANR的其中一
微信终端开发团队
2021/07/14
3.9K0
BlockCanary源码解析
如上代码中的loop()方法是Looper中的,我们的目的是监测主线程的卡顿问题,因为UI更新界面都是在主线程中进行的,所以在主线程中做耗时操作可能会造成界面卡顿,而主线程的Looper早已经在APP启动的时候Android framework里面创建了main looper,那么一个线程对应一个Looper,Looper当中有一个MessageQueue,专门用来接收Handler发送过来的msg,并且在looper()方法中循环去从MessageQueue中去取msg,然后执行,而且是顺序执行的,那么前面一个msg还没处理完,loop()就会等待它处理完了才会再去执行下一个msg,如果前面一个msg处理很慢,那就会造成卡顿了,在msg.target.dispatchMessage(msg)前有:
大大大大大先生
2018/09/04
9220
BlockCanary源码解析
Android性能调优利器StrictMode
作为Android开发,日常的开发工作中或多或少要接触到性能问题,比如我的Android程序运行缓慢卡顿,并且常常出现ANR对话框等等问题。既然有性能问题,就需要进行性能优化。正所谓工欲善其事,必先利其器。一个好的工具,可以帮助我们发现并定位问题,进而有的放矢进行解决。本文主要介绍StrictMode 在Android 应用开发中的应用和一些问题。
技术小黑屋
2018/09/05
1.3K0
Android性能调优利器StrictMode
Android卡顿优化 | 卡顿单点问题监测方案
下面项目准备了几个类型的单点问题模拟, 运行程序,查看logcat: 【注意, 在打印的时候我加了一个logTAG即ARTHookTest, 所以在查看logcat的时候可以定位ARTHookTest这个关键词, 方便调试!!!】 -IPC;IO类型单点问题;
凌川江雪
2020/04/09
2.6K0
Android卡顿优化 | 卡顿单点问题监测方案
6个Android ANR面试题和优化方案
4、 除了Android Studio Profiler,还有哪些工具可以帮助检测ANR?
AntDream
2024/10/08
2400
6个Android ANR面试题和优化方案
Android卡顿优化 | AndroidPerformanceMonitor(BlockCanary)源码详析(真的很详细哦!)
1. 【监控周期的 定义】 blockCanary打印一轮信息的周期, 是从主线程一轮阻塞的开始开始,到阻塞的结束结束,为一轮信息; 这个周期我们也可以成为BlockCanary的监控周期/监控时间段;
凌川江雪
2020/04/09
1.5K0
Android卡顿优化 | AndroidPerformanceMonitor(BlockCanary)源码详析(真的很详细哦!)
Android 性能优化(二)
在大部分Android平台的设备上,Android系统是16ms刷新一次,也就是一秒钟60帧。要达到这种刷新速度就要求在ui线程中处理的任务时间必须要小于16ms,如果ui线程中处理时间长,就会导致跳过帧的渲染,也就是导致界面看起来不流畅,卡顿。如果用户点击事件5s中没反应就会导致ANR。
xiangzhihong
2021/01/22
2.6K0
Android卡顿优化 | 卡顿及其优化工具概述及StrictMode实践案例
项目GitHub 本文要点 一般使用的卡顿优化工具 卡顿问题概述 卡顿问题分析难点 关于CPU Profiler 关于Systrace 关于StrictMode 磁盘读写违例检测实战 实例限制检测实战 一般使用的卡顿优化工具 CPU Profiler Systrace StrictMode (strict adj.精确的; 绝对的; 严格的,严谨的; [植]笔直的 mode n.方式; 状况; 时尚,风尚; 调式 模式;) 卡顿问题概述 很多性能问题(如内存占用高、耗费流量等)都相对不容易被
凌川江雪
2020/04/01
2.5K0
Android卡顿优化 | 卡顿及其优化工具概述及StrictMode实践案例
Android应用ANR分析
在Android中,程序的响应性是由Activity Manager与Window Manager系统服务来负责监控的,当系统检测到下面的条件之一时会显示ANR的对话框:
用户1205080
2019/03/18
1.2K0
一文揭秘如何使用卡顿检测工具--BlockCanary
在日常业务测试中经常会发现页面跳转卡顿、滑动卡顿等卡顿问题,但是我们发现卡顿问题,有时候反馈给开发不一定得到很好的解决,因为开发需要看日志,而每次如果都去抓log,就会显得麻烦,而且需要搜索。会非常麻烦,如何解决了,成为老大难的问题了。
雷子
2021/03/15
1.9K0
一文揭秘如何使用卡顿检测工具--BlockCanary
BlockCanary原理分析
概述 BlockCanary是Android平台上的一个轻量的,非侵入式的性能监控组件,可以在使用应用的时候检测主线程上的各种卡顿问题,并可通过组件提供的各种信息分析出原因并进行修复。 使用 项目地址:https://github.com/markzhai/AndroidPerformanceMonitor Step1. 配置build.gradle dependencies { // most often used way, enable notification to notify block e
用户1205080
2019/04/09
7490
BlockCanary原理分析
Matrix TraceCanary -- 初恋·卡顿
Baby 不要再哭泣,这一幕多么熟悉~ 在使用 App 时,有些人遇上这弹框应该会是一本正经,而有些人看到了估计一脸懵逼(黑人❓)。当然,这里我们要讨论的不是什么初恋,而是对大多数开发者来说,戏虐你千百遍,回头对它如初恋的卡顿。 曾经有篇杂志说“使用一款应用,犹如谈一场恋爱”,当时我觉得这是一本正经地在胡说八道,你手机装了上百款应用,能说这像谈恋爱?但现在想想,其实并非没有道理,当你喜欢上一款应用,往往是因为它的功能足够吸引你,就像你喜欢他的外表,再然后你体验了一段时间(交往),发现这款确实是你喜欢的
微信终端开发团队
2019/01/11
4.4K0
Matrix TraceCanary -- 初恋·卡顿
《广研Android卡顿监控系统》
实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一。Android 由于机型配置和系统的不同,项目复杂App场景丰富,代码多人参与迭代历史较久,代码可能会存在很多UI线程耗时的操作,实际测试时候也会偶尔发现某些业务场景发生卡顿的现象,用户也经常反馈和投诉App使用遇到卡顿。因此,我们越来越关注和提升用户体验的流畅度问题。 已有方案 在这之前,我们将反馈的常见卡顿场景,或测试过程中常见的测试场景使用UI自动化来重复操作,用adb系统工具观察App的卡顿数据情况,试图重现场景来定位问题。 常用的方式是使用
腾讯Bugly
2018/03/23
4.7K2
Android轻量级APM性能监测方案
[GITHUB链接 Collie ](https://github.com/happylishang/Collie)
看书的小蜗牛
2020/09/16
3.9K0
android 线程那点事
在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制的产生,并且线程的创建和销毁都会有相应的开销,当系统中存在大量的线程时,系统会通过时间片轮转的方式调度每个线程,在这么多线程中有一个被称为主线程,主线程是指进程所拥有的线程,在JAVA中默认情况下一个进程只有一个线程,这个线程就是主线程。主线程主要处理界面交互相关的逻辑,因为用户随时会和界面发生交互,因此主线程在任何时候都必须有比较高的响应速度,否则就会产生一种界面卡顿的感觉。为了保持较高的响应速度,这就要求主线程
xiangzhihong
2018/02/02
8630
android 线程那点事
Android面试题之App的卡顿监控和卡顿优化
1、 在主线程中,加载SP,或者是缓存加载,JSON解析,可以放到Idelhander
AntDream
2024/06/24
1980
Android面试题之App的卡顿监控和卡顿优化
相关推荐
Android性能优化(六)之卡顿那些事
更多 >
LV.1
Android
作者相关精选
换一批
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档