重要!!!
明确自己使用的flutter 版本,不同的版本在原生页面承载flutter页面的时候方式不同,我使用的是1.17.1 。studio版本是3.5.2
阿里flutter_boost 插件可以方便的集成flutter module。但是flutter更新的版本很快,不同版本之间的有核心的api是废弃掉。flutter boost更新兼容达不到flutter sdk更新的速度。如果你要集成flutter boost要注意自己的flutter sdk版本和flutter_boost版本的保持统一。
创建项目流程
new -> new project ->//创建Android 原生项目
new -> new module -> flutter module //创建flutter module
此时项目编译 app目录下的build.gradle应该是这样的
在setting.gradle中应该是这样的
此时可以试着分别允许native项目和flutter项目。
下面是核心的类
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
public class FlutterPlatformActivity extends AppCompatActivity {
FlutterEngine mFlutter1Engine;
FlutterView mFlutter1View;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flutter2);
//initFlutterEngine();
mFlutter1Engine=FlutterEngineCache.getInstance().get("my_engine_id");
mFlutter1View = createFlutterView();
mFlutter1View.attachToFlutterEngine(mFlutter1Engine);
}
private FlutterView createFlutterView() {
FlutterView flutterView = new FlutterView(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout flContainer = findViewById(R.id.fl_flutter);
flContainer.addView(flutterView, lp);
flContainer.setVisibility(View.INVISIBLE);
FlutterUiDisplayListener listener = new FlutterUiDisplayListener() {
@Override
public void onFlutterUiDisplayed() {
flContainer.setVisibility(View.VISIBLE);
}
@Override
public void onFlutterUiNoLongerDisplayed() {
}
};
flutterView.addOnFirstFrameRenderedListener(listener);
return flutterView;
}
@Override
protected void onResume() {
super.onResume();
mFlutter1Engine.getLifecycleChannel().appIsResumed();
}
@Override
protected void onPause() {
super.onPause();
mFlutter1Engine.getLifecycleChannel().appIsInactive();
}
@Override
protected void onStop() {
super.onStop();
mFlutter1Engine.getLifecycleChannel().appIsPaused();
}
private void initFlutterEngine() {
mFlutter1Engine = FlutterEngineCache.getInstance().get("flutter");
if (mFlutter1Engine == null) {
mFlutter1Engine = new FlutterEngine(this);
mFlutter1Engine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
FlutterEngineCache.getInstance().put("flutter", mFlutter1Engine);
}
}
}
//有两种方式 第一种在页面中初始化FlutterEngine 第二中在application中初始化 在FlutterEngineCache存储
package com.example.myapplication;
import android.app.Application;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
public class MyApplication extends Application {
private FlutterEngine flutterEngine;
@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(
DartExecutor.DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fl_flutter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</FrameLayout>
</FrameLayout>
官方描述
/**
* A single Flutter execution environment.
*
* <p>The {@code FlutterEngine} is the container through which Dart code can be run in an Android
* application.
*
* <p>Dart code in a {@code FlutterEngine} can execute in the background, or it can be render to the
* screen by using the accompanying {@link FlutterRenderer} and Dart code using the Flutter
* framework on the Dart side. Rendering can be started and stopped, thus allowing a {@code
* FlutterEngine} to move from UI interaction to data-only processing and then back to UI
* interaction.
*
* <p>Multiple {@code FlutterEngine}s may exist, execute Dart code, and render UIs within a single
* Android app. Flutter at this point makes no guarantees on the performance of running multiple
* engines. Use at your own risk. See https://github.com/flutter/flutter/issues/37644 for details.
*
* <p>To start running Dart and/or Flutter within this {@code FlutterEngine}, get a reference to
* this engine's {@link DartExecutor} and then use {@link
* DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}. The {@link
* DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} method must not be invoked twice
* on the same {@code FlutterEngine}.
*
* <p>To start rendering Flutter content to the screen, use {@link #getRenderer()} to obtain a
* {@link FlutterRenderer} and then attach a {@link RenderSurface}. Consider using a {@link
* io.flutter.embedding.android.FlutterView} as a {@link RenderSurface}.
*
* <p>Instatiating the first {@code FlutterEngine} per process will also load the Flutter engine's
* native library and start the Dart VM. Subsequent {@code FlutterEngine}s will run on the same VM
* instance but will have their own Dart <a
* href="https://api.dartlang.org/stable/dart-isolate/Isolate-class.html">Isolate</a> when the
* {@link DartExecutor} is run. Each Isolate is a self-contained Dart environment and cannot
* communicate with each other except via Isolate ports.
*/
1.一个Flutter执行环境 是dart运行在Android上面最小的容器
2.在FlutterEngine中的dart代码 既可以运行在后台,也可以进行(FlutterRenderer)ui交互
3.初始化FlutterEngine时,加载FlutterEngine的native libs并且启动DartVM
4.DartVM中有多个FlutterEngine。
5.FlutterEngine运行在各自的Isolate中(类似于Android中的线程
),他们的内存数据不共享,需要通过Isolate事先设置的port(顶级函数)通讯。
构造方法
只说核心
可以看到在flutterEngine中有几个方法
//Finds Flutter resources in an application APK and also loads Flutter's native library
- FlutterLoader :FlutterLoader 在应用程序APK中查找Flutter资源,并加载Flutter的本机库。
Interface between Flutter embedding's Java code and Flutter engine's C/C++ code.
- FlutterJNI :Flutter嵌入的Java代码和Flutter引擎的C / C ++代码之间的接口。
FlutterRenderer:呈现FlutterEngine
DartExecutor:配置,引导并开始执行Dart代码