欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Flutter Android启动源码分析(一)

程序员文章站 2022-06-25 09:17:08
前言版本:Flutter 1.20.4 stable这个系列主要讲解在Flutter的项目中,Android 从启动到加载Flutter等一系列的过程。本文主要是对FlutterApplication的startInitialization方法及FlutterActivity整个类源码的分析Application

前言

版本:Flutter 1.20.4 stable

这个系列主要讲解在Flutter的项目中,Android 从启动到加载Flutter等一系列的过程。

本文主要是对FlutterApplication的startInitialization方法及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);
  }
}

在Android项目的AndroidManifest.xml中指定了application为FlutterApplication,主要是一个初始化操作

最终会调用FlutterLoader类中的startInitialization方法

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);
  }
  • 加载Flutter引擎的本机库以启用后续的JNI调用
  • 开始定位和打开应用程序APK中打包的Dart资源

FlutterApplication不 做过多分析,就是一些资源的初始化和so库加载的一些操作

FlutterActivity

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

它是继承Activity并实现了FlutterActivityAndFragmentDelegate这个代理类中的Host接口及获取生命周期的LifecycleOwner接口

构造函数里实例化了一个LifecycleRegistry,它继承Lifecycle

public class LifecycleRegistry extends Lifecycle

然后实现LifecycleOwner接口的getLifecycle方法,返回了LifecycleRegistry对象,用于生命周期状态的监听和通知,这个不用过多介绍

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

onCreate方法

@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();
  }
  @NonNull
  private View createFlutterView() {
    return delegate.onCreateView(
        null /* inflater */, null /* container */, null /* savedInstanceState */);
  }

对于主题和状态栏的设置我们不去关注,重点看一下configureWindowForTransparency这个方法和对FlutterActivityAndFragmentDelegate的一些操作

configureWindowForTransparency

如果FlutterActivity背景模式是透明(默认是不透明的模式),则设置整个FlutterActivity窗口透明及隐藏状态栏

其实如果我们不在原生项目中使用FlutterModule进行混合开发的话,是不需要关注这个方法的。因为默认就是非透明模式。

这里只是先提一嘴,后续讲到混合开发时会涉及到这个方法的一些配置

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

FlutterActivityAndFragmentDelegate

  1. 主要是实例化了FlutterActivityAndFragmentDelegate,传递FlutterActivityAndFragmentDelegate.Host实现类即当前类this
  2. 调用delegate.onAttach、onActivityCreated及onCreateView方法
  3. 关于FlutterActivityAndFragmentDelegate的介绍,我们放到下一篇文章里

其他生命周期方法大同小异,基本都是通过LifecycleRegistry.handleLifecycleEvent设置当前界面状态。然后将当前生命周期委托给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);
  }

接下来就是一些重写FlutterActivityAndFragmentDelegate.Host接口的方法

/* package */ interface Host
      extends SplashScreenProvider, FlutterEngineProvider, FlutterEngineConfigurator {

我们先看一下这个Host接口具体有哪些方法

下面根据其用途进行了一个大致的分类

  • 获取Context、Activity、Lifecycle

    方法名 描述
    Context getContext(); 获取上下文对象
    Activity getActivity(); 获取activity对象
    Lifecycle getLifecycle(); 获取Lifecycle,返回的就是上面说的LifecycleRegistry
  • 实例化FlutterEngine

    方法名 描述
    String getCachedEngineId(); 缓存的FlutterEngine Id
    FlutterEngine provideFlutterEngine(@NonNull Context context); 提供一个FlutterEngine,目前版本返回null,暂不考虑
    FlutterShellArgs getFlutterShellArgs(); 初始化参数
    boolean shouldAttachEngineToActivity(); 建立Engine和Activity的连接关系,控制界面用于向附加到 FlutterEngine的插件提供Android资源和生命周期事件。
    PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine); 提供一个PlatformPlugin(Android平台的插件实现)
  • 在FlutterView里首次运行Dart所需参数

    方法名 描述
    String getAppBundlePath(); 返回包含dart代码的app bundle 路径
    String getInitialRoute(); 初始化路由路径
    String getDartEntrypointFunctionName(); dart代码执行入口函数名称
  • 实例化FlutterSplashView(启动界面及整个FlutterView)

    方法名 描述
    RenderMode getRenderMode(); Flutter UI 渲染模式,默认是surface
    TransparencyMode getTransparencyMode(); 透明度模式,默认是opaque
    void onFlutterSurfaceViewCreated(@NonNull FlutterSurfaceView flutterSurfaceView); FlutterSurfaceView创建回调
    void onFlutterTextureViewCreated(@NonNull FlutterTextureView flutterTextureView); FlutterTextureView创建回调
    void onFlutterUiDisplayed(); FlutterView首次渲染回调
    void onFlutterUiNoLongerDisplayed(); FlutterView停止渲染回调
    SplashScreen provideSplashScreen(); 返回一个SplashScreen
    方法名 描述
    boolean shouldDestroyEngineWithHost(); 是否清理engine

这里我们只对configureFlutterEngine方法实现做详细分析,剩余的在下篇文章中具体说明

configureFlutterEngine 插件注册方法

在FlutterActivityAndFragmentDelegate.onAttach方法中进行调用

void onAttach(@NonNull Context context) {
		// 省略部分代码
    host.configureFlutterEngine(flutterEngine);
}

FlutterActivity对其实现如下

 @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.");
    }
  }

这里通过反射执行GeneratedPluginRegistrant.registerWith方法来注册pubspec.yaml中添加的插件依赖

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

registerWith方法中的 flutterEngine.getPlugins().add(xxx)无需我们手动添加,当执行pub get 时,如果含原生插件,则flutter会自动去添加,而且其实如果我们不注册自己的原生插件的话,这个方法其实也是不需要去做任何操作的。默认都是自动注册。这个方法及其业务逻辑在最近Flutter几个版本的更新中有很大的变化

如果我们要注册自己的原生插件,则需要在MainActivity中重写configureFlutterEngine并调用super.configureFlutterEngine,然后通过 flutterEngine.plugins.add方法进行注册

class MainActivity : FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // 原生封装的FlutterPlugin需要手动进行注册
        flutterEngine.plugins.add(ToastPlugin())
    }
}

总结

通过本文我们可以学习到

  1. FlutterApplication主要做了哪些工作
  2. MainActivity继承的FlutterActivity主要做了哪些工作

以上内容如有不准确的地方,麻烦大家在评论区指出,我会一一改正

下篇文章会分析FlutterActivityAndFragmentDelegate这个代理类的一些逻辑,这个类比较关键,它是主要负责FlutterActivity和FlutterEngine、FlutterView、PlatformPlugin等一些联动工作,比如Engine注册、Dart执行、平台插件实现以及Activity和Engine生命周期的一些控制等等,同时会衍生出很多类。可以说这篇文章只是一个起点,核心业务在后面。

本文地址:https://blog.csdn.net/fighting_android/article/details/108700276

相关标签: Flutter android