开发React Native 应用笔记

1.onResponderMove有时候返回值不对的问题

在做进度条的时候,处理onResponderMove的事件的时候,有时候发现进度条在拖动的时候跳动,最后发现原因是onResponderMove返回的event值有些问题。

这是布局

{return true}}
                 onMoveShouldSetResponder = {()=>{return true}}
                 onResponderStart = {this._onResponderStart.bind(this)}
                 onResponderMove = {this._onResponderMove.bind(this)}
                 onResponderRelease = {this._onResponderRelease.bind(this)}
                 onLayout = {this._onLayout.bind(this)}>

               
               
               
               

最后发现是因为view堆叠在一块,触摸的时候事件返回的位置信息有点问题。最好处理就是事件只让最外面View处理就行路。

最后查看资料有一个叫pointerEvent的属性,是用来处理堆叠在一起的View事件的属性。看路文档之后最后选择“box-only”完美解决

pointerEvent官方介绍
pointerEvent参考

2.onResponderMove的参数event.nativeEvent.locationX不会更新的问题

这是React Native的一个bug,正在Android中出现,IOS没有问题
参见issue

在最新的版本中已经修复了,但是在低版本中有问题
还好event.nativeEvent.pageX这个值更新了,就用这个值来解决问题就行了
解决办法如下:

var x = event.nativeEvent.locationX;
        if (Platform.OS === "android"){
            x = event.nativeEvent.pageX - this.layout.x
        }

在0.44.3中是有问题的,最新版本修复此bug

3.Component的生命周期控制

我本人是做原生开发的,遇到这个问题是做视频全屏切换需求的时候,要是原生开发其实就很简单了,直接将VideoView放到Activity的根View当中就可以了,这样切换的时候,VideoView不会被销毁在重新创建。天真的我在ReactNative当中也想这也搞,最后发现你根本控制不了Component的生命周期。

假设VideoComponent对应的原生的VideoViewMananger。那么在VideoComponent挂载的时候会调用VideoViewManager的createNewInstance来创建新的实例。在卸载的时候也会调用onDropViewInstance。

所以在RN当中,View组件的节点与节点之间的层级一般是不能改变的。并不能简单的像在原生开发当中,将一个View移除,在添加到另一个ViewGroup当中。

4.React Native 没有遵守Android的View的测量,布局,绘制,这个流程

在RN自定义View组件的时候,在自定义的View组件中掉用requestLayout不会引发重新布局的。
原因:在ReactRootView当中的onLayout没事实现

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    // No-op since UIManagerModule handles actually laying out children.
  }

所以布局到ReactRootView就停止了,不会继续传递下去。

这会有什么问题呢?会让你在自定义一些复杂组件的时候,内部的View如果需要重新布局,可能就很麻烦。

假如,我们要做一个VideoView的组件,VideoView可能是一个RelativeLayout,里面放一个SurfaceView。一般在mediaPlayer回调视频宽高的方法的时候需要对SurfaceView重新计算大小和布局,这是就要发送一个requestLayout请求。

在RN下一般没反应的,肯定不会重新布局。而RN的源码中给了一个临时方案

  private final Runnable measureAndLayout = new Runnable() {
    @Override
    public void run() {
      measure(
          MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
          MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
      layout(getLeft(), getTop(), getRight(), getBottom());
    }
  };

  @Override
  public void requestLayout() {
    super.requestLayout();

    // The spinner relies on a measure + layout pass happening after it calls requestLayout().
    // Without this, the widget never actually changes the selection and doesn't call the
    // appropriate listeners. Since we override onLayout in our ViewGroups, a layout pass never
    // happens after a call to requestLayout, so we simulate one here.
    post(measureAndLayout);
  }

这段代码是在ReactPicker这个类当中复制过来的。

5. React Native 的View 的设计

6.在View组件中onDraw函数

在自定义组件中调用invalidate()会引发视图重绘,RN的绘制也有很大问题。

7. Modal这个类在Android上最好不要用

Modal根本没有考虑上面有对话框的问题,如果Modal覆盖有对话框,从后台切换到前台,Modal会覆盖对话框。
而且Modal的在前后胎切换的时候体验很不好,会重复创建。

8.react native send command to a non-existing view

在JS对接Android原生View的时候出现的。

JS:
            
                this.start()}
                    { ... this.props}
                />
            

Java:
    @Nullable
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        Map map = new HashMap<>();
        map.put("WL_onPreparedEvent" , MapBuilder.of("registrationName", "onPreparedEvent"));
        return map;
    }

由于事件不会冒泡传,所以只看最外层的View没有onPreparedEvent就报错了。

方案:去掉最外的View或者用getExportedCustomBubblingEventTypeConstants

9. RN和Kotlin写的模块对接的时候编译的bug

用Kotlin写的模块,对接RN的时候,模块的名字正确没有重复,但是在JS端总是获取不到对象。

const module = NativeModules.xxxxx; //总是返回null

可能是Kotlin编译的问题,clean一下项目在运行就可以了

你可能感兴趣的:(开发React Native 应用笔记)