React Native填坑之旅--開啟TurboModule(Android)

小紅星閃啊閃發表於2021-10-16

FB宣傳了N多年的新架構估計很多人都熟知了。最主要的改進就是從所有通訊都通過非同步Bridge的方式轉為直接通訊的方式。減少訊息通訊延遲,提高效能。這其中最關鍵的就是TurboModule

開啟TurboModule

開啟TurboModule沒有文件。只有就的原生module裡夾雜著隻言片語。一個例子就把開發同學帶到react-native的程式碼裡了。這說明官方早就支援這個機制了,只是沒正式官宣。但是複雜度太高,還需要對react-native的repo程式碼結構有了解。還有一個更好的例子react-native-animated

這個專案大小適中,結構也不那麼複雜。很適合類比研究,實現。

實現NativeModule

和之前一樣,繼承ReactContextBaseJavaModule。具體可以參考這裡實現getName方法

新增ReactModule註解

這是和之前的方式不同的一點。

現在程式碼看起來是這樣的:


@ReactModule(name = ReanimatedModule.NAME)
public class ReanimatedModule extends ReactContextBaseJavaModule {

  public static final String NAME = "ReanimatedModule";

  public ReanimatedModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

  @Override
  public String getName() {
    return NAME;
  }
}

最後新增ReactMethod

  @ReactMethod
  public void animateNextTransition(int tag, ReadableMap config) {
    mTransitionManager.animateNextTransition(tag, config);
  }

原生模組這部分就完事兒了。下面看看如何註冊這個原生模組。

註冊原生模組

這個部分就是重點了。上一節,和之前開發原生模組唯一不同的點就是多了一個@ReactModule的註解。這一部分不同的地方就有點多,按照官網的說法是比之前稍微多了幾步。

1. 新增一個繼承了TurboReactPackage的類

public class ReanimatedPackage extends TurboReactPackage {}

2. 實現getModule方法

  @Override
  public NativeModule getModule(String name, ReactApplicationContext reactContext) {
    if (name.equals(ReanimatedModule.NAME)) {
      return new ReanimatedModule(reactContext);
    }

    return null;
  }

3. 實現getReactModuleInfoProvider

  @Override
  public ReactModuleInfoProvider getReactModuleInfoProvider() {
    Class<? extends NativeModule>[] moduleList =
        new Class[] {
          ReanimatedModule.class, ReanimatedUIManager.class,
        };

    final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
    for (Class<? extends NativeModule> moduleClass : moduleList) {
      ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);

      reactModuleInfoMap.put(
          reactModule.name(),
          new ReactModuleInfo(        // *
              reactModule.name(),
              moduleClass.getName(),
              true,
              reactModule.needsEagerInit(),
              reactModule.hasConstants(),
              reactModule.isCxxModule(),
              TurboModule.class.isAssignableFrom(moduleClass)));
    }

    return new ReactModuleInfoProvider() {
      @Override
      public Map<String, ReactModuleInfo> getReactModuleInfos() {
        return reactModuleInfoMap;
      }
    };
  }

在這裡Module的名字依然扮演了重要的角色,它是把前(JS)後(原生),在原生裡註冊的多個原生模組之間如何找到那個模組都需要這模組名稱。所以在初始化ReactModuleInfo的時候第一個引數就是模組名稱。

第三個引數canOverrideExistingModule,一般在你還有不是TurboModules的時候最好是設定為false

needEgerInit如果你需要這個模組懶載入的話設定為false。除非你要你的app在初始化的時候也一起初始化你的模組。這樣會增加開機時間。

hasConstant如果你的模組有常量匯出的話設定為true

isCxxModuletrue如果程式碼都是C程式碼。

isTurboModule如果當前模組是turbo module設定為true。不是為false。這個引數在這裡是因為ReactModuleInfo不是隻服務於turbo module的。

4. 在Application裡註冊Package

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          // ...
          new ReanimatedPackage(), //*
          // ...
      );
    }
}

在方法getPackages()裡註冊ReanimatedPackage()物件。

總結

FB對React Native架構的優化主要集中在優化效能。在具體的開發活動裡,主要就是利用turbo module來使用新架構的優化。加快開機速度,讓動畫更流暢,讓長列表滾動更加流暢。

相關文章