微信越滑越卡

这篇文章是我的朋友小二哥写的,他解决了一个问题并提交了一个补丁给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,一经查实,立即删除!

相关文章

MFC中五个初始类的作用

MFC中五个初始类的作用 https://blog.csdn.net/thisispan/article/details/7393401

扁平化可伸展导航

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

重新整理了下mount/umount,免得老是不来新机忘记了

挂接就是将分离的文件系统附加到文件系统分成结构中。文件系统要附加到某个挂接点&#xff0c;也就是目录。 挂接和卸载文件系统发生在系统启动和关闭时。 系统启动时&#xff0c;将读取/etc/vfstab文件。这个文件记录系统要挂接的文件系统。因此/etc/vfstab文件中的文件系统…

C++ —— C++内联函数

C内联函数 一、内联函数 1、C中的const常量可以替代宏常数定义&#xff0c;如&#xff1a; const int A 3; #define A 3 C中是否有解决方案替代宏代码片段呢&#xff1f;&#xff08;替代宏代码片段就可以避免宏的副作用&#xff01;&#xff09; 2、C中推荐使用内联函数…

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

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

CWinThread

https://baike.baidu.com/item/CWinThread/5902501 https://blog.51cto.com/5412097/1643861 https://blog.csdn.net/thanklife/article/details/78677688 CWinThread&#xff1a;&#xff1a;SuspendThread https://blog.csdn.net/h315444352/article/details/22091361 工作者…

html总结:文本框填满表格

<style> input { width: 100%; }</style>转载于:https://www.cnblogs.com/iCheny/p/8798808.html

双硬盘奇怪问题...

今天下午打开文件夹....提示错误....指定的文件夹无法打开....汗...文件夹大小变成0KB..而有的文件夹又是正常的...可以打开,可以访问....一切正常...但是就是那么几个文件夹.里面放的东西比较的多....打不开...由于本人是双硬盘.上次出现了RAW 的错误...让我有一种一朝被蛇咬,…

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

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

C++ —— C++数据类型

C—— C数据类型 1、数据类型分类 &#xff08;1&#xff09;基本数据类型 字符型&#xff08;char&#xff09;—— 1字节 整型&#xff08;int&#xff09; —— 4字节 浮点型&#xff08;实型&#xff09;—— 单精度float4字节&#xff1b;双精度&#xff08;double&a…

参加 CSDN 2009 英雄大会有感(一)

参加 CSDN 2009 英雄大会有感&#xff08;一&#xff09; 我作为 CSDN Blog 专家参加了本次盛会。今天可以算是本次大会的第一天。下午参观了 CSDN 的研发中心&#xff0c;感觉蛮不错&#xff0c;从个人工作环境布局到各会议室的空间布局上都很紧凑&#xff0c;合理、最大化地…

不要怕辛苦

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

SQL Server 连接字符串和身份验证 学习

https://www.cnblogs.com/niuyjdz/p/7533439.html

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

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

区分JavaScript中的undefined,null和NaN

区分underfined,null和NaN 先看看下面语句的运行结果&#xff1a; 1: var a; 2: alert(a); //显示"undefined" 3: alert(typeof a); //显示"undefined" 4: alert(b); //显示"undefined" 以上说明a的值和类型都是underfined 1: var a null; …

C++ —— C++常量和变量

C——常量和变量 1、常量 &#xff08;1&#xff09;整型常量 指不带小数点的整数&#xff0c;整型常量后面加上l或L表示该数为长整型常量 整型常量后面加上u或U表示该数为无符号整型常量 十进制中&#xff0c;由&#xff0c;&#xff0d;&#xff0c;0~9组成 &#xff08…

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

荧光数码管是用来显示数字和符号的器件。它的数码字形由若千段分立的笔划构成。荧光数码管是一种电真空器件&#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;许多计算机操作系统为应用…

洛谷 P2084 进制转换

P4122 [USACO17DEC]Blocked Billboard 题目描述 During long milking sessions, Bessie the cow likes to stare out the window of her barn at two huge rectangular billboards across the street advertising "Farmer Alexs Amazingly Appetizing Alfalfa" and &…