preface

Version: Flutter 1.20.4 stable

This series focuses on the process of Android starting up and loading a Flutter project.

This paper mainly analyzes the startInitialization method of FlutterApplication and the whole source code of FlutterActivity

Application

<application android:name="io.flutter.app.FlutterApplication" android:label="flutter_channel" android:icon="@mipmap/ic_launcher"> public class FlutterApplication extends Application { @Override @CallSuper public void onCreate() { super.onCreate(); FlutterMain.startInitialization(this); }}Copy the code

Application is specified as FlutterApplication in the Androidmanifest.xml of the Android project, and is primarily an initialization operation

The startInitialization method in the FlutterLoader class is eventually called

public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) { if (this.settings ! = null) { return; } if (Looper.myLooper() ! = Looper.getMainLooper()) { throw new IllegalStateException("startInitialization must be called on the main thread"); } applicationContext = applicationContext.getApplicationContext(); this.settings = settings; long initStartTimestampMillis = SystemClock.uptimeMillis(); initConfig(applicationContext); initResources(applicationContext); System.loadLibrary("flutter"); VsyncWaiter.getInstance( (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE)) .init(); long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis; FlutterJNI.nativeRecordStartTimestamp(initTimeMillis); }Copy the code
  • Load the local library of the Flutter engine to enable subsequent JNI calls
  • Start locating and opening the Dart resources packaged in the application APK

FlutterApplication does not do too much analysis, just some initialization of resources and some operations of so library loading

FlutterActivity

class MainActivity : FlutterActivity(){}
Copy the code
 public class FlutterActivity extends Activity
    implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner {
 
 public FlutterActivity() {
    lifecycle = new LifecycleRegistry(this);
  }
Copy the code

It is to inherit the Activity and realizes the proxy class FlutterActivityAndFragmentDelegate acquisition life cycle of the Host interface and LifecycleOwner interface

The constructor instantiates a LifecycleRegistry that inherits Lifecycle

public class LifecycleRegistry extends Lifecycle
Copy the code

I then implement the getLifecycle method of the LifecycleOwner interface, which returns the LifecycleRegistry object for listening on and notifying LifecycleOwner status, which I don’t need to go into too much detail

 @Override
  @NonNull
  public Lifecycle getLifecycle() {
    return lifecycle;
  }
Copy the code

The onCreate method

@Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    switchLaunchThemeForNormalTheme();
    super.onCreate(savedInstanceState);
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    delegate = new FlutterActivityAndFragmentDelegate(this);
    delegate.onAttach(this);
    delegate.onActivityCreated(savedInstanceState);
    configureWindowForTransparency();
    setContentView(createFlutterView());
    configureStatusBarForFullscreenFlutterExperience();
  }
Copy the code
  @NonNull
  private View createFlutterView() {
    return delegate.onCreateView(
        null /* inflater */, null /* container */, null /* savedInstanceState */);
  }
Copy the code

For the subject and the status bar set, we don’t pay attention to key see configureWindowForTransparency this method and some actions of FlutterActivityAndFragmentDelegate

configureWindowForTransparency

If the FlutterActivity background mode is transparent (default is opaque), make the entire FlutterActivity window transparent and hide the status bar

If we didn’t mix development with FlutterModule in a native project, we wouldn’t have to worry about this approach. Because the default is opaque.

This is just a quick mention, but I’ll cover some configuration of this method when I talk about mixed development

private void configureWindowForTransparency() { BackgroundMode backgroundMode = getBackgroundMode(); if (backgroundMode == BackgroundMode.transparent) { getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); }}Copy the code

FlutterActivityAndFragmentDelegate

  1. Main is instantiated FlutterActivityAndFragmentDelegate, transfer FlutterActivityAndFragmentDelegate. Host implementation class that is the current class this
  2. Call the delegate.onAttach, onActivityCreated and onCreateView methods
  3. About FlutterActivityAndFragmentDelegate introduction, we are on the next article

Other life cycle method is the same, basic it is through LifecycleRegistry. HandleLifecycleEvent set the current interface state. The current life cycle is then delegated to a delegate

 @Override
  protected void onStart() {
    super.onStart();
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
    delegate.onStart();
  }

  @Override
  protected void onResume() {
    super.onResume();
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    delegate.onResume();
  }

  @Override
  public void onPostResume() {
    super.onPostResume();
    delegate.onPostResume();
  }

  @Override
  protected void onPause() {
    super.onPause();
    delegate.onPause();
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
  }
Copy the code

Then there is some rewriting FlutterActivityAndFragmentDelegate. The Host interface

/* package */ interface Host
      extends SplashScreenProvider, FlutterEngineProvider, FlutterEngineConfigurator {
Copy the code

So let’s take a look at what the methods are for this Host interface

The following is a rough classification according to its use

  • Get Context, Activity, Lifecycle

    The method name describe
    Context getContext(); Getting context objects
    Activity getActivity(); Get the Activity object
    Lifecycle getLifecycle(); LifecycleRegistry will be returned when Lifecycle is retrieved
  • Instantiation FlutterEngine

    The method name describe
    String getCachedEngineId(); The FlutterEngine Id of the cache
    FlutterEngine provideFlutterEngine(@NonNull Context context); A FlutterEngine is provided. The current version returns NULL
    FlutterShellArgs getFlutterShellArgs(); Initialization parameter
    boolean shouldAttachEngineToActivity(); Establish a connection between the Engine and Activity, and the control interface is used to provide Android resources and lifecycle events to plug-ins attached to the FlutterEngine.
    PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine); Provide a PlatformPlugin (plugin implementation for Android platform)
  • Parameters required to run Dart for the first time in FlutterView

    The method name describe
    String getAppBundlePath(); Returns the app Bundle path containing the DART code
    String getInitialRoute(); Example Initialize a routing path
    String getDartEntrypointFunctionName(); The DART code executes the entry function name
  • Instantiate FlutterSplashView (launch interface and the entire FlutterView)

    The method name describe
    RenderMode getRenderMode(); Flutter UI rendering mode, default is Surface
    TransparencyMode getTransparencyMode(); Transparency mode, the default is Opaque
    void onFlutterSurfaceViewCreated(@NonNull FlutterSurfaceView flutterSurfaceView); FlutterSurfaceView creates the callback
    void onFlutterTextureViewCreated(@NonNull FlutterTextureView flutterTextureView); FlutterTextureView creates the callback
    void onFlutterUiDisplayed(); FlutterView renders the first callback
    void onFlutterUiNoLongerDisplayed(); FlutterView stops rendering callbacks
    SplashScreen provideSplashScreen(); Return a SplashScreen
    The method name describe
    boolean shouldDestroyEngineWithHost(); Whether to clean engine

Here we only analyze the configureFlutterEngine method implementation in detail, the rest will be explained in the next article

ConfigureFlutterEngine Plug-in registration method

In FlutterActivityAndFragmentDelegate onAttach method call

Void onAttach (@ NonNull Context Context) {/ / omit part of the code host. ConfigureFlutterEngine (flutterEngine); }Copy the code

FlutterActivity implements it as follows

 @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    registerPlugins(flutterEngine);
  }
  private static void registerPlugins(@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.w(
          TAG,
          "Tried to automatically register plugins with FlutterEngine ("
              + flutterEngine
              + ") but could not find and invoke the GeneratedPluginRegistrant.");
    }
  }
Copy the code

Here by reflecting execution GeneratedPluginRegistrant. RegisterWith method to register the pubspec. Yaml adding plugin dependencies

@Keep public final class GeneratedPluginRegistrant { public static void registerWith(@NonNull FlutterEngine flutterEngine) { flutterEngine.getPlugins().add(new com.befovy.fijkplayer.FijkPlugin()); }}Copy the code

There is no need to manually add flutterengine.getplugins ().add(XXX) to the registerWith method. When pub get is performed, native plug-ins are added to flutter automatically and if we do not register our native plug-ins, This method doesn’t actually need to do anything. The default is automatic registration. This method and its business logic have changed a lot in recent updates to Flutter

If we want to register your own native plugin, you need to rewrite configureFlutterEngine in the MainActivity and call the super. ConfigureFlutterEngine, Then through flutterEngine. Plugins. The add method to register

class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super. ConfigureFlutterEngine (FlutterEngine) / / primary packaging FlutterPlugin need to manually register flutterEngine.plugins.add(ToastPlugin()) } }Copy the code

conclusion

We can learn from this article

  1. What does FlutterApplication do
  2. What does MainActivity inherit from FlutterActivity do

If the above content is inaccurate, please point out in the comments section, I will correct one by one

Next article will analyze FlutterActivityAndFragmentDelegate some logic of the proxy class, this class is the key, It is mainly responsible for some linkage work of FlutterActivity, FlutterEngine, FlutterView, PlatformPlugin, etc. Examples include Engine registration, Dart execution, platform plug-in implementation, and some control over the Activity and Engine life cycles. This article is just a starting point. The core business comes later.