Android 启动普通的Flutter screen


文章目录

  • Android 启动普通的Flutter screen
  • 将FlutterActivity添加到AndroidManifest.xml
  • 启动FlutterActivity
  • 使用缓存的FlutterEngine
  • 带有缓存引擎的初始路由
  • 添加半透明的Flutter屏幕
  • 使用半透明的主题
  • 启动用透明度的FlutterActivity
  • Android 关于FlutterEngine 加载flutter的问题


将FlutterActivity添加到AndroidManifest.xml

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />

对@style/LaunchTheme的引用可以被任何想要应用到FlutterActivity的Android主题所代替

主题的选择决定了应用到Android系统chrome上的颜色,比如Android的导航条,以及在Flutter UI首次呈现之前FlutterActivity的背景颜色

启动FlutterActivity

startActivity(FlutterActivity.createDefaultIntent(MainActivity.class));

前面的示例假设您的Dart入口点称为main(),而您的初始Flutter路由为’ / '。Dart进入点不能使用Intent来改变,但是初始路线可以使用Intent来改变。下面的示例演示如何启动一个FlutterActivity,该活动最初在Flutter中呈现一个自定义路由

startActivity(
      FlutterActivity
        .withNewEngine()
        .initialRoute("/my_route")
        .build(this)
      );

将“/my_route”替换为您想要的初始路由。

使用withNewEngine()工厂方法配置一个FlutterActivity,该活动在内部创建自己的FlutterEngine实例。这带来了一个重要的初始化时间。另一种方法是指示FlutterActivity使用预先预热的、缓存的FlutterEngine,这将最小化Flutter的初始化时间。下面将讨论这种方法

使用缓存的FlutterEngine

默认情况下,每个FlutterActivity都创建自己的FlutterEngine。每个FlutterEngine都有一个非平凡的预热时间。这意味着在您的Flutter体验变得可见之前,启动一个标准的FlutterActivity会有一个短暂的延迟。为了尽量减少这种延迟,你可以在到达你的FlutterActivity之前预热一个FlutterEngine,然后你可以使用你的预热过的FlutterEngine。

要预热一个FlutterEngine,请在应用程序中找到一个合理的位置来实例化一个FlutterEngine。下面的示例在Appl中任意预热一个FlutterEngine

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // Instantiate a FlutterEngine.
    flutterEngine = new FlutterEngine(this);

    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartEntrypoint.createDefault()
    );

    // Cache the FlutterEngine to be used by FlutterActivity.
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine);
  }
}

传给FlutterEngineCache的ID可以是任何你想要的。确保将相同的ID传递给任何应该使用缓存的FlutterEngine的FlutterActiity或FlutterFragment。接下来将讨论如何在缓存的FlutterEngine中使用FlutterActivity。

Note:要预热一个FlutterEngine,你必须执行一个Dart entrypoint。请记住,在调用executeDartEntrypoint()的那一刻,您的Dart entrypoint方法就开始执行了。如果您的Dart entrypoint调用runApp()来运行一个Flutter应用程序,那么Flutter app的行为就像它在一个零大小的窗口中运行,直到这个FlutterEngine被附加到一个FlutterActivity、FlutterFragment或FlutterView上。请确保您的应用程序的运转在预热和显示Flutter 的内容之间。

有了预先预热的缓存的FlutterEngine,现在需要指示您的FlutterActivity使用缓存的FlutterEngine,而不是创建一个新的FlutterEngine。为此,使用FlutterActivity的withCachedEngine()构建器:

startActivity(
      FlutterActivity
        .withCachedEngine("my_engine_id")
        .build(currentActivity)
      );

在使用withCachedEngine()工厂方法时,传递与缓存所需的FlutterEngine时相同的ID。现在,当您启动FlutterActivity时,Flutter内容的显示延迟明显减少。

Note:当使用缓存的FlutterEngine时,该FlutterEngine比任何显示它的FlutterActivity或FlutterFragment都要长。请记住,在对FlutterEngine进行预热之后,Dart代码就开始执行,并在销毁FlutterActivity/FlutterFragment之后继续执行。要停止执行并清除资源,从FlutterEngineCache获取您的FlutterEngine并使用FlutterEngine.destroy().销毁它

Note:运行时性能并不是预热和缓存FlutterEngine的唯一原因。预热的FlutterEngine独立于FlutterActivity执行Dart代码,这使得这样的FlutterEngine可以在任何时候执行任意Dart 代码。非ui应用程序逻辑可以在FlutterEngine(如网络和数据缓存)中执行,也可以在服务或其他地方的后台行为中执行。当使用FlutterEngine在后台执行行为时,一定要遵守所有Android对后台执行的限制

注意:Flutter的 debug/release版本具有截然不同的性能特征。要评估Flutter的性能,请使用release构建。

带有缓存引擎的初始路由

带有缓存引擎的初始路由当配置一个新的FlutterEngine的FlutterActivity或FlutterFragment时,可以使用初始路由的概念。但是,当使用缓存引擎时,FlutterActivity和FlutterFragment没有提供初始路由的概念。这是因为缓存的引擎应该已经在运行Dart代码了,这意味着现在配置初始路由已经太晚了。希望缓存引擎从自定义初始路由开始的开发人员可以配置缓存的FlutterEngine,在执行Dart入口点之前使用自定义初始路由。下面的示例演示如何使用带有缓存引擎的初始路由

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // Instantiate a FlutterEngine.
    flutterEngine = new FlutterEngine(this);
    // Configure an initial route.
    flutterEngine.getNavigationChannel().setInitialRoute("your/route/here");
    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartEntrypoint.createDefault()
    );
   // Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine);
  }
}

通过设置导航通道的初始路由,关联的FlutterEngine在初始执行runApp() Dart函数时显示所需的路由

在初始执行runApp()之后更改导航通道的初始路由属性没有效果。希望在不同的Activitys和Fragments之间使用相同的FlutterEngine并在这些显示之间切换路由的开发人员需要设置一个方法通道,并显式地指示他们的Dart代码更改导航器路由。

添加半透明的Flutter屏幕

要使您的FlutterActivity透明,请对创建和启动FlutterActivity的常规过程进行以下更改

使用半透明的主题

Android需要一个特殊的主题属性为Activitys渲染一个半透明的背景。使用以下属性创建或更新Android主题:

<style name="MyTheme" parent="@style/MyParentTheme">
  <item name="android:windowIsTranslucent">true</item>
</style>

然后,将半透明的主题应用到你的FlutterActivity中

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/MyTheme"
  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />

你的FlutterActivity现在支持半透明。接下来,您需要使用显式透明支持来启动FlutterActivity

启动用透明度的FlutterActivity

要在透明的背景下启动FlutterActivity,请将适当的BackgroundMode传递给IntentBuilder

startActivity(
  FlutterActivity
    .withNewEngine()
    .backgroundMode(FlutterActivity.BackgroundMode.transparent)
    .build(context)
);

// Using a cached FlutterEngine.
startActivity(
  FlutterActivity
    .withCachedEngine("my_engine_id")
    .backgroundMode(FlutterActivity.BackgroundMode.transparent)
    .build(context)
);

现在您有了一个具有透明背景的FlutterActivity

注意:确保你的Flutter content也包括一个半透明的背景。如果您的Flutter UI绘制了一个实心的背景色,那么它看起来仍然像是您的FlutterActivity拥有一个不透明的背景。

Android 关于FlutterEngine 加载flutter的问题

初始化了引擎,不管是使用FlutterActivity.withNewEngine()还是FlutterActivity.withCachedEngine,

Dart的main()函数都会执行,StatefulWidget中的State的initState方法也会调用,请查看使用缓存的FlutterEngine

ter的问题

初始化了引擎,不管是使用FlutterActivity.withNewEngine()还是FlutterActivity.withCachedEngine,

Dart的main()函数都会执行,StatefulWidget中的State的initState方法也会调用,请查看使用缓存的FlutterEngine