FlatList和ScrollView是RN中两种列表,但在测试过程中发现部分机型频繁滑动时偶现会和实际方向相反,于是就开始调查什么原因,网上搜了一下,并没有找到相关的内容,于是只能看代码了。。
首先,看js代码中FlatList和ScrollView是如何实现的,对应的原生控件是什么
ScrollView比较简单,代码一开始就暴露出来了
if (Platform.OS === 'android') {
AndroidScrollView = requireNativeComponent('RCTScrollView');
AndroidHorizontalScrollView = requireNativeComponent(
'AndroidHorizontalScrollView',
);
AndroidHorizontalScrollContentView = requireNativeComponent(
'AndroidHorizontalScrollContentView',
);
} else if (Platform.OS === 'ios') {
RCTScrollView = requireNativeComponent('RCTScrollView');
RCTScrollContentView = requireNativeComponent('RCTScrollContentView');
} else {
RCTScrollView = requireNativeComponent('RCTScrollView');
RCTScrollContentView = requireNativeComponent('RCTScrollContentView');
}
可以确定对应的是RCTScrollView这个view,搜一下果然找到了对应原生的ReactScrollViewManager,真正是组件是ReactScrollView,而且是继承的是原生的ScrollView,先到这里,一会再研究
再看FlatList,FlatList就比较复杂了,通过代码可以发现其实是由VirtualizedList实现的,而且都在同一个目录下
再通过VirtualizedList代码可以发现,其实也是由ScrollView实现的,那么只要研究RCTScrollView就好了
接下来,就定位为啥会和滑动方向相反
首先要确定是不是真的是这个类的原因,我写了个测试页面,设置了一个足够长的滑动页面,在连续的滑动过程中果然出现了这个bug,而直接使用原生的ScrollView是没有这个问题的,那么就可以确定问题就是ReactScrollView造成的
既然是滑动方向的问题,肯定和onTouchEvent,onScrollChanged,fling这些方法有关系,最后定位到了fling,这个方法,而且发现方法中有这样一段注释
@Override
public void fling(int velocityY) {
// Workaround.
// On Android P if a ScrollView is inverted, we will get a wrong sign for
// velocityY (see https://issuetracker.google.com/issues/112385925).
// At the same time, mOnScrollDispatchHelper tracks the correct velocity direction.
//
// Hence, we can use the absolute value from whatever the OS gives
// us and use the sign of what mOnScrollDispatchHelper has tracked.
final int correctedVelocityY = (int)(Math.abs(velocityY) * Math.signum(mOnScrollDispatchHelper.getYFlingVelocity()));
这段代码竟然就是为了解决滑动方向的问题而加的,我有点慌,这是什么情况,通过打印日志,发现由于加了这段确实偶发的会出现correctedVelocityY和velocityY的值相同,但符号刚好相反,而此时就会发生方向相反的现象
难道是为了修复Android P上的问题,反而把其他版本该出问题了??
我测试了一下Android P的手机,貌似没有这个问题,之前有问题的手机,更新了Android系统后这个问题也没有出现了
虽然无法完全确定,但貌似就是我猜测的这样。。只能无奈的笑了