在上一篇中我介绍了Android和Flutter如何实现混合编译,我们这篇就要学习怎么实现Android页面打开一个Flutter页面。
建议使用FlutterBoost进行页面之间的跳转,本文仅用来学习官方的demo
老规矩,我们先要把官方教程摆出来 英文官网 Native Flutter页面路由跳转,官方思路是有两种:
- Adding a Flutter screen to an Android app (添加一个Flutter Screen,可以理解为Activity)
- Adding a Flutter Fragment to an Android app (添加一个Flutter Fragment)
1 准备工作,一定要看哈~
app的AndroidManifest.xml文件中增加以下代码:
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>
2 添加一个Flutter Screen
2.1不指定页面(有黑屏延迟,不建议采用)
startActivity(FlutterActivity.createDefaultIntent(currentActivity) );
2.2指定页面 (有黑屏延迟,不建议采用)
//这里的initialRoute就是指定要跳转的Flutter页面,你想跳转哪个就要先在Flutter里面注册,再在Native中使用
Intent intent = FlutterActivity.withNewEngine().initialRoute("/my_route").build(this);
这两种方式是最简单的,同时也是性能最差的,从Native页面过渡到Flutter页面会出现短暂的黑屏延迟,非常影响体验感
为什么会出现黑屏延迟呢?
Every FlutterActivity creates its own FlutterEngine by default. Each FlutterEngine has a non-trivial warm-up time. This means that launching a standard FlutterActivity comes with a brief delay before your Flutter experience becomes visible. To minimize this delay, you can warm up a FlutterEngine before arriving at your FlutterActivity, and then you can use your pre-warmed FlutterEngine instead.
每一个FlutterActivity创建都对应一个FlutterEngine的创建,而FlutterEngine创建有自己的“预热”时间,这就意味着FlutterActivity页面可见之前需要等待FlutterEngine预热,所以此时屏幕是黑色的,等预热之后,页面才回变得可见。
于是乎降低这个黑屏延迟的方案就有了!——提前预热FlutterEngine
在哪里预热呢?这个要看你的逻辑而定了,下面是在Application中初始化的,仅供参考。
2.3不指定页面(黑屏延迟很短,可以使用)
public class NativeApplication extends Application {
FlutterEngine flutterEngine;
@Override
public void onCreate() {
super.onCreate();
flutterEngine = new FlutterEngine(this);
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}
}
//页面跳转
Intent intent = FlutterActivity.withCachedEngine("my_engine_id").build(this);
2.4指定页面(黑屏延迟很短,可以使用)
public class NativeApplication extends Application {
FlutterEngine flutterEngine;
@Override
public void onCreate() {
super.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(
DartExecutor.DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}
}
//页面跳转
Intent intent = FlutterActivity.withCachedEngine("my_engine_id").build(this);
咸鱼开源的Flutter_Boost对这个启动做了优化,等后续我会持续更新的,这里先按照官方的文档学习
3 添加一个Flutter Fragment
英文官方文档在这里 Adding a Flutter Fragment to an Android app
public class SecondActivity extends FragmentActivity {
private static final String TAG_FLUTTER_FRAGMENT = "flutter_fragment";
private FlutterFragment flutterFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
FragmentManager fragmentManager = getSupportFragmentManager();
if (flutterFragment == null) {
flutterFragment = FlutterFragment.createDefault();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, flutterFragment).commit();
}
}
}
除此之外你还需要将Activity生命周期方法回调给FlutterFragment,这里就直接贴原文的代码了。
public class MyActivity extends FragmentActivity {
@Override
public void onPostResume() {
super.onPostResume();
flutterFragment.onPostResume();
}
@Override
protected void onNewIntent(@NonNull Intent intent) {
flutterFragment.onNewIntent(intent);
}
@Override
public void onBackPressed() {
flutterFragment.onBackPressed();
}
@Override
public void onRequestPermissionsResult(
int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults
) {
flutterFragment.onRequestPermissionsResult(
requestCode,
permissions,
grantResults
);
}
@Override
public void onUserLeaveHint() {
flutterFragment.onUserLeaveHint();
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
flutterFragment.onTrimMemory(level);
}
}
当然还是会出现短暂延迟,你也可以采取之前提到的“预热引擎”的方式,由于代码高度一致,这里不再展示了。