ReactNative源码分析之NativeModule调用堆栈分析

本文详细分析了ReactNative中NativeModule的使用、注册、ReactInstanceManager创建流程以及JavaModuleWrapper的调用过程。从创建自定义NativeModule,实现ReactPackage,到NativeModule如何注册到框架,再到JS调用Java层NativeModule的方法,揭示了ReactNative中Java到C++的交互机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当前分析的ReactNative版本为0.61.5:

一、NativeModule基本使用

我们知道,要想访问原生提供的功能,需要通过继承NativeModule,并提供相关的方法,只有这样JS层才能直接访问。

举个例子,StatusBarModule类:

/** {@link NativeModule} that allows changing the appearance of the status bar. */
@ReactModule(name = StatusBarModule.NAME)
public class StatusBarModule extends ReactContextBaseJavaModule {
   

  @Override
  public String getName() {
   
    return NAME;
  }
  
  @ReactMethod
  public void setColor(final int color, final boolean animated) {
   
    final Activity activity = getCurrentActivity();
    if (activity == null) {
   
      FLog.w(
          ReactConstants.TAG,
          "StatusBarModule: Ignored status bar change, current activity is null.");
      return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   

      UiThreadUtil.runOnUiThread(
          new GuardedRunnable(getReactApplicationContext()) {
   
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void runGuarded() {
   
              activity
                  .getWindow()
                  .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
              if (animated) {
   
                int curColor = activity.getWindow().getStatusBarColor();
                ValueAnimator colorAnimation =
                    ValueAnimator.ofObject(new ArgbEvaluator(), curColor, color);

                colorAnimation.addUpdateListener(
                    new ValueAnimator.AnimatorUpdateListener() {
   
                      @Override
                      public void onAnimationUpdate(ValueAnimator animator) {
   
                        activity
                            .getWindow()
                            .setStatusBarColor((Integer) animator.getAnimatedValue());
                      }
                    });
                colorAnimation.setDuration(300).setStartDelay(0);
                colorAnimation.start();
              } else {
   
                activity.getWindow().setStatusBarColor(color);
              }
            }
          });
    }
  }

  ....
  
}

我们看到,StatusBarModule继承ReactContextBaseJavaModule,而该类父类最终会实现NativeModule接口。

我们再来看getName方法,该方法提供NativeModule的名称,供JS层直接访问。

最后,再来看setColor方法,该方法有个注解ReactMethod,该注解说明该方法直接暴露给JS层,供JS层直接调用。

二、NativeModule如何被注册

既然我们定义了这样的一个Module类,那么这些类是如何被注册进ReactNative框架中的呢?

ReactNative提供了ReactPackage接口,我们看下这个接口的说明:

/**
 * Main interface for providing additional capabilities to the catalyst framework by couple of
 * different means:
 *
 * <ol>
 *   <li>Registering new native modules
 *   <li>Registering new JS modules that may be accessed from native modules or from other parts of
 *       the native code (requiring JS modules from the package doesn't mean it will automatically
 *       be included as a part of the JS bundle, so there should be a corresponding piece of code on
 *       JS side that will require implementation of that JS module so that it gets bundled)
 *   <li>Registering custom native views (view managers) and custom event types
 *   <li>Registering natively packaged assets/resources (e.g. images) exposed to JS
 * </ol>
 *
 * <p>TODO(6788500, 6788507): Implement support for adding custom views, events and resources
 */
public interface ReactPackage {
   

  /**
   * @param reactContext react application context that can be used to create modules
   * @return list of native modules to register with the newly created catalyst instance
   */
  @NonNull
  List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext);

  /** @return a list of view managers that should be registered with {@link UIManagerModule} */
  @NonNull
  List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext);
}

要实现这个接口,需要实现createNativeModules和createViewManagers这两个方法,createViewManagers方法我们先忽略,后续会讲。createNativeModules方法需要关注。当实现这个接口,需要实现createNativeModules方法,返回我们自定义的NativeModule类。

这样我们就实现了一个ReactPackage。那我们自定义的ReactPackage如何注册进框架里?

接着分析,在我们使用ReactNative时候,需要继承ReactNativeHost抽象类,该类里有个方法getPackages,返回自定义的ReactPackage就可以。

三、ReactInstanceManager创建流程

在讲解ReactInstanceManager创建之前,最好先了解ReactContext创建流程,可以参考如下这篇文章:
ReactNative源码分析之ReactContext创建流程.

创建ReactContext流程中,会先创建ReactInstanceManager类,我们看下代码:

/* package */ ReactInstanceManager(
      Context applicationContext,
      @Nullable Activity currentActivity,
      @Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
      JavaScriptExecutorFactory javaScriptExecutorFactory,
      @Nullable JSBundleLoader bundleLoader,
      @Nullable String jsMainModulePath,
      List<ReactPackage> packages,
      boolean useDeveloperSupport,
      @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
      LifecycleState initialLifecycleState,
      @Nullable UIImplementationProvider mUIImplementationProvider,
      NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
      @Nullable RedBoxHandler redBoxHandler,
      boolean lazyViewManagersEnabled,
      @Nullable DevBundleDownloadListener devBundleDownloadListener,
      int minNumShakes,
      int minTimeLeftInFrameForNonBatchedOperationMs,
      @Nullable JSIModulePackage jsiModulePackage,
      @Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
   
    Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()");
    initializeSoLoaderIfNecessary(applicationContext);

    DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext);

    mApplicationContext = applicationContext;
    mCurrentActivity = currentActivity;
    mDefaultBackButtonImpl = defaultHardwareBackBtnHandler;
    mJavaScriptExecutorFactory = javaScriptExecutorFactory;
    mBundleLoader = bundleLoader;
    mJSMainModulePath = jsMainModulePath;
    mPackages = new ArrayList<>();
    mUseDeveloperSupport = useDeveloperSupport;
    Systrace.beginSection(
        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.initDevSupportManager");
    mDevSupportManager =
        DevSupportManagerFactory.create
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值