Flutter插件原理及初始化过程

前言

本篇分析基于flutter 2.5.1源码

Flutter 2.5.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision ffb2ecea52 (6 months ago) • 2021-09-17 15:26:33 -0400
Engine • revision b3af521a05
Tools • Dart 2.14.2
复制代码

一.FLutterPlugin的启动过程

1.1 FlutterActivity启动

  • 一般情况下,我们会继承FlutterActivity作为我们的flutter页面元素的承载者。比如FLutterboostActivity.
  • 启动activity执行onCreate方法
protected void onCreate(@Nullable Bundle savedInstanceState) {
    switchLaunchThemeForNormalTheme();

    super.onCreate(savedInstanceState);

    delegate = new FlutterActivityAndFragmentDelegate(this);
    delegate.onAttach(this);
    delegate.onRestoreInstanceState(savedInstanceState);

    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);

    configureWindowForTransparency();

    setContentView(createFlutterView());

    configureStatusBarForFullscreenFlutterExperience();
  }
复制代码

1.2 FlutterActivityAndFragmentDelegate.onAttach

它的作用有两个

  • 初始化FlutterEngine
  • 注册插件,这里的host实际上就是FLutterActivity或者FlutterFragment
void onAttach(@NonNull Context context) {
    ensureAlive();

    if (flutterEngine == null) {
      setupFlutterEngine();
    }

    if (host.shouldAttachEngineToActivity()) {
      Log.v(TAG, "Attaching FlutterEngine to the Activity that owns this delegate.");
      flutterEngine.getActivityControlSurface().attachToActivity(this, host.getLifecycle());
    }

    platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);

    host.configureFlutterEngine(flutterEngine);
  }
复制代码

1.3 FlutterActivityAndFragmentDelegate.setupFlutterEngine

  • 采用缓存的flutterEngine或者构造新的flutterEngine
  • flutterEngine 是dart代码的运行时环境,初始化了常用的darvm到jvm的channel,用于渲染的flutterRender等。
  • isFlutterEngineFromHost注意这个,它表示flutterEngine是从已有的FlutterActivity共享的还是重新创建的。
void setupFlutterEngine() {
    Log.v(TAG, "Setting up FlutterEngine.");

    // First, check if the host wants to use a cached FlutterEngine.
    String cachedEngineId = host.getCachedEngineId();
    if (cachedEngineId != null) {
      flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
      isFlutterEngineFromHost = true;
      if (flutterEngine == null) {
        throw new IllegalStateException(
            "The requested cached FlutterEngine did not exist in the FlutterEngineCache: '"
                + cachedEngineId
                + "'");
      }
      return;
    }

    // Second, defer to subclasses for a custom FlutterEngine.
    flutterEngine = host.provideFlutterEngine(host.getContext());
    if (flutterEngine != null) {
      isFlutterEngineFromHost = true;
      return;
    }

    // Our host did not provide a custom FlutterEngine. Create a FlutterEngine to back our
    // FlutterView.
    Log.v(
        TAG,
        "No preferred FlutterEngine was provided. Creating a new FlutterEngine for"
            + " this FlutterFragment.");
    flutterEngine =
        new FlutterEngine(
            host.getContext(),
            host.getFlutterShellArgs().toArray(),
            /*automaticallyRegisterPlugins=*/ false,
            /*willProvideRestorationData=*/ host.shouldRestoreAndSaveState());
    isFlutterEngineFromHost = false;
  }
复制代码

1.4 FlutterEngine

public FlutterEngine(
      @NonNull Context context,
      @Nullable FlutterLoader flutterLoader,
      @NonNull FlutterJNI flutterJNI,
      @NonNull PlatformViewsController platformViewsController,
      @Nullable String[] dartVmArgs,
      boolean automaticallyRegisterPlugins,
      boolean waitForRestorationData) {
    AssetManager assetManager;
    try {
      assetManager = context.createPackageContext(context.getPackageName(), 0).getAssets();
    } catch (NameNotFoundException e) {
      assetManager = context.getAssets();
    }

    FlutterInjector injector = FlutterInjector.instance();

    if (flutterJNI == null) {
      flutterJNI = injector.getFlutterJNIFactory().provideFlutterJNI();
    }
    this.flutterJNI = flutterJNI;

    this.dartExecutor = new DartExecutor(flutterJNI, assetManager);
    this.dartExecutor.onAttachedToJNI();

    DeferredComponentManager deferredComponentManager =
        FlutterInjector.instance().deferredComponentManager();

    accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI);
    deferredComponentChannel = new DeferredComponentChannel(dartExecutor);
    keyEventChannel = new KeyEventChannel(dartExecutor);
    lifecycleChannel = new LifecycleChannel(dartExecutor);
    localizationChannel = new LocalizationChannel(dartExecutor);
    mouseCursorChannel = new MouseCursorChannel(dartExecutor);
    navigationChannel = new NavigationChannel(dartExecutor);
    platformChannel = new PlatformChannel(dartExecutor);
    restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
    settingsChannel = new SettingsChannel(dartExecutor);
    systemChannel = new SystemChannel(dartExecutor);
    textInputChannel = new TextInputChannel(dartExecutor);

    if (deferredComponentManager != null) {
      deferredComponentManager.setDeferredComponentChannel(deferredComponentChannel);
    }

    this.localizationPlugin = new LocalizationPlugin(context, localizationChannel);

    if (flutterLoader == null) {
      flutterLoader = injector.flutterLoader();
    }

    if (!flutterJNI.isAttached()) {
      flutterLoader.startInitialization(context.getApplicationContext());
      flutterLoader.ensureInitializationComplete(context, dartVmArgs);
    }

    flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
    flutterJNI.setPlatformViewsController(platformViewsController);
    flutterJNI.setLocalizationPlugin(localizationPlugin);
    flutterJNI.setDeferredComponentManager(injector.deferredComponentManager());

    // It should typically be a fresh, unattached JNI. But on a spawned engine, the JNI instance
    // is already attached to a native shell. In that case, the Java FlutterEngine is created around
    // an existing shell.
    if (!flutterJNI.isAttached()) {
      attachToJni();
    }

    // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if
    // possible.
    this.renderer = new FlutterRenderer(flutterJNI);

    this.platformViewsController = platformViewsController;
    this.platformViewsController.onAttachedToJNI();

    this.pluginRegistry =
        new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, flutterLoader);

    // Only automatically register plugins if both constructor parameter and
    // loaded AndroidManifest config turn this feature on.
    if (automaticallyRegisterPlugins && flutterLoader.automaticallyRegisterPlugins()) {
      GeneratedPluginRegister.registerGeneratedPlugins(this);
    }
  }
复制代码

如果是自动注册plugins,则触发plugins的注册流程,默认情况下为false

1.5 FlutterActivityAndFragmentDelegate.Host.configureFlutterEngine

如果是复用的FlutterEngine,则不重复初始化plugins。一般第一次启动FlutterAcitivity时isFlutterEngineFromHost=false此时执行registerGeneratedPlugins

public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    if (delegate.isFlutterEngineFromHost()) {
      
      return;
    }

    GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
  }
复制代码

1.6 GeneratedPluginRegister.registerGeneratedPlugins

public static void registerGeneratedPlugins(@NonNull FlutterEngine flutterEngine) {
    try {
      Class<?> generatedPluginRegistrant =
          Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
      Method registrationMethod =
          generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
      registrationMethod.invoke(null, flutterEngine);
    } catch (Exception e) {
      Log.e(
          TAG,
          "Tried to automatically register plugins with FlutterEngine ("
              + flutterEngine
              + ") but could not find or invoke the GeneratedPluginRegistrant.");
      Log.e(TAG, "Received exception while registering", e);
    }
  }
复制代码

通过反射的形式找到自动生成的GeneratedPluginRegistrant类,调用其静态方法registerWith

1.7 GeneratedPluginRegistrant.registerWith

public final class GeneratedPluginRegistrant {
  private static final String TAG = "GeneratedPluginRegistrant";
  public static void registerWith(@NonNull FlutterEngine flutterEngine) {
    try {
      flutterEngine.getPlugins().add(new io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin());
    } catch(Exception e) {
      Log.e(TAG, "Error registering plugin flutter_plugin_android_lifecycle, io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin", e);
    }
    try {
      flutterEngine.getPlugins().add(new com.huya.flutterbridge.FlutterbridgePlugin());
    } catch(Exception e) {
      Log.e(TAG, "Error registering plugin flutterbridge, com.huya.flutterbridge.FlutterbridgePlugin", e);
    }
    ...
  }
}
复制代码

将所有由pubspec.yaml中引入的插件,注册到插件管理器中

dependencies:
  image_picker: ^0.8.4
  video_player: ^2.1.14
  webview_flutter: ^2.0.12
复制代码

1.8 FlutterEngineConnectionRegistry.add

public void add(@NonNull FlutterPlugin plugin) {
   
   
    plugins.put(plugin.getClass(), plugin);
    plugin.onAttachedToEngine(pluginBinding);

    if (plugin instanceof ActivityAware) {
      ActivityAware activityAware = (ActivityAware) plugin;
      activityAwarePlugins.put(plugin.getClass(), activityAware);

      if (isAttachedToActivity()) {
        activityAware.onAttachedToActivity(activityPluginBinding);
      }
    }

   
    if (plugin instanceof ServiceAware) {
      ServiceAware serviceAware = (ServiceAware) plugin;
      serviceAwarePlugins.put(plugin.getClass(), serviceAware);

      if (isAttachedToService()) {
        serviceAware.onAttachedToService(servicePluginBinding);
      }
    }

    
    if (plugin instanceof BroadcastReceiverAware) {
      BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
      broadcastReceiverAwarePlugins.put(plugin.getClass(), broadcastReceiverAware);

      if (isAttachedToBroadcastReceiver()) {
        broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
      }
    }

    
    if (plugin instanceof ContentProviderAware) {
      ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
      contentProviderAwarePlugins.put(plugin.getClass(), contentProviderAware);

      if (isAttachedToContentProvider()) {
        contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
      }
    }
  }
复制代码
  • 首先触发了plugin.onAttachedToEngine方法回调
  • 将plugin按照类型分别加入到不同的map中,比如将实现了ActivityAware的插件加入到activityAwarePlugins中。

FlutterEngineConnectionRegistry.attachToActivity

public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
    Log.v(
        TAG,
        "Attaching to an Activity: "
            + activity
            + "."
            + (isWaitingForActivityReattachment ? " This is after a config change." : ""));
    if (this.exclusiveActivity != null) {
      this.exclusiveActivity.detachFromFlutterEngine();
    }
    // If we were already attached to an app component, detach from it.
    detachFromAppComponent();

    if (this.exclusiveActivity != null) {
      throw new AssertionError("Only activity or exclusiveActivity should be set");
    }
    this.activity = activity;
    attachToActivityInternal(activity, lifecycle);
  }


private void attachToActivityInternal(@NonNull Activity activity, @NonNull Lifecycle lifecycle) {
    this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle);

    // Activate the PlatformViewsController. This must happen before any plugins attempt
    // to use it, otherwise an error stack trace will appear that says there is no
    // flutter/platform_views channel.
    flutterEngine
        .getPlatformViewsController()
        .attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor());

    // Notify all ActivityAware plugins that they are now attached to a new Activity.
    for (ActivityAware activityAware : activityAwarePlugins.values()) {
      if (isWaitingForActivityReattachment) {
        activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding);
      } else {
        activityAware.onAttachedToActivity(activityPluginBinding);
      }
    }
    isWaitingForActivityReattachment = false;
  }
复制代码

这里会遍历activityAwarePlugins中的插件,回调生命周期方法onAttachedToActivity,其他的生命周期方法依次类推 。

二.plugin的定义

flutter工具提供了自定义插件的方法

flutter create --org com.xxx --template=plugin --platforms=android,ios -a java -i swift flutterbridge
复制代码

新建出来的项目在pubspec.yaml中会定义插件的信息

flutter:
  uses-material-design: true
  assets:
    - lib/HiveBusiness/assets/
  plugin:
    platforms:
      android:
        package: com.xxx.flutterbridge
        pluginClass: FlutterbridgePlugin
      ios:
        pluginClass: FlutterbridgePlugin
复制代码

2.1 FlutterbridgePlugin

定义plugin的目的是为了做dartvm和native的通信,也同时提供一些native能力。 一般我们需要处理两件事

  • plugin中处理生命周期方法,主要是在onAttachedToEngine的时候做初始化
  • 将native的能力封装成channel通信参数提交给dart侧使用。

关于如何定义一个完整的的插件,后续篇幅分析。

猜你喜欢

转载自juejin.im/post/7074897567762350093