微信越滑越卡

这篇文章是我的朋友小二哥写的,他解决了一个问题并提交了一个补丁给google合入,当然了,这也是他第一次提交补丁被google采纳。我觉得这才是做技术的样子,二哥也很喜欢篮球,,为二哥吹一波。哈哈。

关于这次补丁的提交如下文,喜欢的同学可以好好看看。




背景

在一个已经加载完成很长的微信聊天记录中,持续不断的滑动,慢慢的微信会越滑越卡。

一、卡顿的原因分析

Choreographer#doFrame的animation中会堆积大量的Callback-AbsListView#FlingRunnable
从而导致了最后这一帧的绘制超时,导致了卡顿。

二、FlingRunnable堆积的原因

一次滑动会触发一个Down事件,多个Move事件,一个Up事件。
从下图可以发现,这次滑动,导致animation的FlingRunnable从3个增加到了4个

看看这4个是怎么来的:

3个是来自于之前的FlingRunnable,新增的一个来自于Up事件触发的。

三、代码分析

3.1 onTouchDown

Touch Down事件会触发mFlingRunnable.flywheelTouch()

    private void onTouchDown(MotionEvent ev) {...if (mTouchMode == TOUCH_MODE_OVERFLING) {...} else {...if (!mDataChanged) { //ListView的数据没有更新if (mTouchMode == TOUCH_MODE_FLING) {//ListView处于Fling的状态// Stopped a fling. It is a scroll.createScrollingCache();mTouchMode = TOUCH_MODE_SCROLL;mMotionCorrection = 0;motionPosition = findMotionRow(y);mFlingRunnable.flywheelTouch();//跳转到3.1.1...

3.1.1 mFlingRunnable.flywheelTouch

flywheelTouch会postdelay一个mCheckFlywheel延迟40ms。
当mCheckFlywheel被执行的时候,会去判断ListView当前的滑动速度。

如果Math.abs(yvel) >= mMinimumVelocity,将会再次postdelay一个mCheckFlywheel,让ListView继续滑动一段时间。
如果Math.abs(yvel) < mMinimumVelocity,将会endFling(),这就是为什么ListView滑动之后慢慢停止的逻辑。

endFling中将会removeCallbacks(this)和removeCallbacks(mCheckFlywheel)

        private static final int FLYWHEEL_TIMEOUT = 40; // millisecondsvoid flywheelTouch() {postDelayed(mCheckFlywheel, FLYWHEEL_TIMEOUT);}private final Runnable mCheckFlywheel = new Runnable() {@Overridepublic void run() {...if (Math.abs(yvel) >= mMinimumVelocity&& scroller.isScrollingInDirection(0, yvel)) {// Keep the fling alive a little longer//yvel > mMinimumVelocity继续滑动,将mCheckFlywheel在推迟40mspostDelayed(this, FLYWHEEL_TIMEOUT);} else {endFling();mTouchMode = TOUCH_MODE_SCROLL;reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);}}};void endFling() {...removeCallbacks(this);removeCallbacks(mCheckFlywheel);...}

3.2 onTouchUp

在onTouchUp中将会执行mFlingRunnable.start(-initialVelocity),从而postOnAnimation(this);

    private void onTouchUp(MotionEvent ev) {switch (mTouchMode) {...case TOUCH_MODE_SCROLL:...if (!dispatchNestedPreFling(0, -initialVelocity)) {if (mFlingRunnable == null) {mFlingRunnable = new FlingRunnable();}reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);mFlingRunnable.start(-initialVelocity);//跳到下面的start方法dispatchNestedFling(0, -initialVelocity, true);} else {mTouchMode = TOUCH_MODE_REST;reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);}...}void start(int initialVelocity) {...postOnAnimation(this);...}

3.3 FlingRunnable#run

FlingRunnable的run方法,如果ListView处于TOUCH_MODE_SCROLL或者TOUCH_MODE_FLING的状态,并且还有更多的内容,就会继续postOnAnimation(this)

@Override
public void run() {switch (mTouchMode) {default:endFling();return;case TOUCH_MODE_SCROLL:if (mScroller.isFinished()) {return;}// Fall throughcase TOUCH_MODE_FLING: {...if (more && !atEnd) {if (atEdge) invalidate();mLastFlingY = y;postOnAnimation(this);} else {...}break;}...}
}

小结:

onTouchDown会postdelay 40ms一个mCheckFlywheel,mCheckFlywheel将会检查ListView是否应该停止

onTouchUp会postOnAnimation(FlingRunnable),让ListView开始Fling起来。

每一个FlingRunnable又会再次触发一个postOnAnimation(FlingRunnable)。

四、对比分析

4.1 为什么Google Pixel不存在这个BUG

原来Google Pixel每次滑动Down和Move事件的间隔绝大多数情况下大于40ms,从而导致mCheckFlywheel中endFling可以在持续的滑动中被有效的执行,这样子就不会导致FlingRunnable的堆积

4.2 为什么我们的手机会存在这个BUG

原来我们的手机TP采样率比较高,接近180hz,Down和Move的时间间隔竟然在9ms左右,从而导致了mCheckFlywheel永远被postdelay,无法有效的执行endFling,这样子就导致了FlingRunnable的堆积

五、解决方案

在FlingRunnable.start中调用postOnAnimation之前removeCallbacks(this),避免FlingRunnable的堆积
这个方案已经被merge进了Android官方主分支中:
https://android-review.googlesource.com/c/platform/frameworks/base/+/1645426

void start(int initialVelocity) {int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;mLastFlingY = initialY;mScroller.setInterpolator(null);mScroller.fling(0, initialY, 0, initialVelocity,0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);mTouchMode = TOUCH_MODE_FLING;mSuppressIdleStateChangeCall = false;removeCallbacks(this);//修复的patchpostOnAnimation(this);if (PROFILE_FLINGING) {if (!mFlingProfilingStarted) {Debug.startMethodTracing("AbsListViewFling");mFlingProfilingStarted = true;}}if (mFlingStrictSpan == null) {mFlingStrictSpan = StrictMode.enterCriticalSpan("AbsListView-fling");}
}

总结

这是我作为android工程师第一次成功提交代码到Android官方主分支,还是值得纪念的,可惜提交的账户不是我自己的,而是公司账户,因为自己的账户很有可能Google工程师不会review你的提交。有了一次就会有第二次,期待我下次继续为Android开源代码贡献代码。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

扁平化可伸展导航

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>扁平化可伸展导航[原创]</title><link rel"stylesheet" type"text/css" href"nav.css"><link rel"stylesheet" t…

大佬为何可以把单片机描述得如此形象生动?

某年某日某产房&#xff0c;你诞生了&#xff08;power up , 上电运行&#xff09;&#xff0c;结果你不哭&#xff0c;医生把你提起来&#xff0c;屁股上狠狠一巴掌&#xff0c;你哇哇大哭&#xff08;reset, 复位成功&#xff09;&#xff0c;护士给你检查&#xff0c;看有没…

51单片机温度控制系统报警器,不会做课程设计的就拿走

▌功能说明&#xff08;1&#xff09;单片机读取温度传感器当前的温度值并在LCD液晶显示屏上的第一行显示当前的温度值&#xff0c;如Temp&#xff1a;27.5℃。&#xff08;2&#xff09;单片机读取按键状态并通过人为手动按键部分来设置最低温度到最高温度的温度范围后&#x…

不要怕辛苦

先说点事情一直以来我都非常喜欢跟大家交流各种问题&#xff0c;自我觉得回答比较用心&#xff0c;可能最近因为很多人毕业&#xff0c;遇到抉择的问题比较多&#xff0c;所以这类的提问也偏多一些。从开始做公众号到现在&#xff0c;支持我的人很多。有些读者从开始关注到现在…

Win7系统中用anaconda配置tensorflow运行环境

前言&#xff1a;anaconda是一个python Data Science Platform。安装它的契机是因为要用tensorflow。安装完后感觉用它来管理python运行环境还是挺方便的&#xff0c;常用的conda命令&#xff1a;升级conda: conda update conda安装conda环境&#xff1a; conda create -n env_…

拆解前苏联产荧光数码管计算器,内部电路结构彪悍!

荧光数码管是用来显示数字和符号的器件。它的数码字形由若千段分立的笔划构成。荧光数码管是一种电真空器件&#xff0c;其工作原理与普通的电子管相似&#xff0c;它的灯丝就是阴极&#xff08;为直热式阴极&#xff09;&#xff0c;当灯丝通电后灯丝就会发热&#xff08;即阴…

silverlight之datagrid的一个问题

this.myDataGrid.itemSourcesitems; 使用泛型数组给datagrid添加itemsource,我想添加一个textblock对象,上面text"sdfd",可运行显示是System.Windows.Controls.TextBlock,如图,请大侠们指点 转载于:https://www.cnblogs.com/wuli00/archive/2009/04/20/1439677.html

什么是套接字(Socket)

什么是套接字(Socket) 应用层通过传输层进行数据通信时&#xff0c;TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要 通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接&#xff0c;许多计算机操作系统为应用…

三极管构成的电流负反馈放大器

▌1.题目设计一个有三极管构成的电流负反馈放大器&#xff0c;放大倍数不小于100倍&#xff0c;集电极最大电流不超过20mA&#xff0c;当负载由1000欧姆变10欧姆时&#xff0c;要求输出电流的波动幅度小于5%。▌2.项目总体功能图▌3.测试条件频率为500HZ、幅度为5mv的正弦波。▌…

lzg_ad:FBWF配置详解

在安装好Windows XP Embedded FP2007及以后版本的开发工具后&#xff0c;我们就可以在我们的XPE操作系统镜像中添加FBWF功能了。我们可以在目标设计器中配置FBWF&#xff0c;也就是在构建XPE镜像文件前配置好FBWF&#xff0c;也可以在运行时镜像中配置FBWF。本文将详细介绍这两…

耦合,到底是什么!?

在电路中,将前级电路(信号源)的能量递至后级电路(负载)称为耦合&#xff0c;常见的耦合介质有导线、电容器&#xff0c;变压器、光电耦合器&#xff0c;电子电路&#xff0c;根据不同耦合介质常见有以下耦合方式&#xff0c;这几种耦合方式&#xff0c;各有特点,在不同哪种比较…

三极管的“非教科书式”解析,什么正偏、反偏都统统滚蛋!

什么正偏&#xff0c;反偏都统统滚蛋&#xff01;&#xff01;&#xff01;❤三极管有三个工作状态&#xff1b;截止、放大、饱和&#xff1b;放大状态很有学问也很复杂&#xff0c;多用于集成芯片&#xff0c;比如运放&#xff0c;现在不讨论&#xff1b;其实对信号的放大我们…

一行代码还能这么秀

老早就想写这篇文章了&#xff0c;因为我经常用用这个方法来装逼&#xff0c;今天终于要把这个装逼方法分享给大家了。我从来不会告诉别人我自己的微信公众号关注早就已经超过40万了。看下面的截图这张截图建议大家保存下&#xff0c;如果遇到不公的事情&#xff0c;你就跟他说…

Linux Select

Linux Select 在Linux中&#xff0c;我们可以使用select函数实现I/O端口的复用&#xff0c;传递给 select函数的参数会告诉内核&#xff1a; •我们所关心的文件描述符 •对每个描述符&#xff0c;我们所关心的状态。(我们是要想从一个文件描述符中读或者写&#xff0c;还…

搞懂图像二值化算法

传统的机器视觉通常包括两个步骤&#xff1a;预处理和物体检测。而沟通二者的桥梁则是图像分割&#xff08;Image Segmentation&#xff09;[1]。图像分割通过简化或改变图像的表示形式&#xff0c;使得图像更易于分析。举个例子&#xff0c;食品加工厂新进了一批肉鸡&#xff…

JavaWeb无限级分销结构分析

在现实生活中我们经常遇到由推荐人注册&#xff0c;比如一个购物平台,用户A推荐用户B注册&#xff0c;那当B购买商品成功时&#xff0c;用户A就会拿到相应的提成。只要是用户A推荐的用户购买商品成功后&#xff0c;A用户都会拿到提成。 当用户B推荐了用户C&#xff0c;那当用户…

一个风骚的C语言操作

有个小伙伴在我们的嵌入式交流群里发了类似下面的一张图&#xff0c;顿时引起一阵骚动&#xff0c;我把源代码再附上&#xff0c;main.c 如下&#xff1a;#include <stdio.h> #include <string.h>static char city_name[][20] { #include "city.h" };in…

SQL Server表分区-水平分区

SQL Server表分区&#xff0c;sql server水平分区 转自&#xff1a;http://www.cnblogs.com/knowledgesea/p/3696912.html 根据时间的&#xff0c;直接上T-SQL代码的水平分区&#xff1a;https://www.xuebuyuan.com/1817312.html?tdsourcetags_pcqq_aiomsg什么是表分区 一般情…

基于STC89C52的韦根数据接收

韦根是一种开放的通讯协议&#xff0c;具体官方介绍如下&#xff1a;Wiegand协议是国际上统一的标准&#xff0c;有很多格式&#xff0c;标准的26-bit 应该是最常用的格式。此外&#xff0c;还有34-bit 、37-bit 等格式。格式的含义如下&#xff1a;当给出这一串数字&#xff0…

超乎想象,数据揭示自学成才的码农为何备受青睐

你是否想成为一个 Web 开发者&#xff0c;但却不知道从哪里开始&#xff1f; 你是否对学习编程语言的大量建议和繁琐细节感到审美疲劳&#xff1f; 你是否不确定需要遵循哪条路才能成为一个自信而又足智多谋的开发者&#xff1f; 如果你的回答是肯定的&#xff0c;那么不要担心…