android FlutterFragment 引入 Flutter ,dartEntrypoint配置多引擎,使用MethodChannel 双向数据交互通信
FlutterFragment 是 Flutter 提供的一个组件,用于在 Android 原生应用中嵌入 Flutter 模块作为 Fragment 使用。
FlutterFragment 允许开发者将 Flutter 视图集成到现有的 Android 应用架构中,作为 Fragment 使用。这种方式比使用 FlutterActivity 更加灵活,可以更好地与现有的 Android 导航和 UI 结构集成。
1. 基本创建方式
// 使用默认配置创建 FlutterFragment
FlutterFragment flutterFragment = FlutterFragment.createDefault();
2. 使用自定义配置创建
// 使用构建器模式创建自定义配置的 FlutterFragment
FlutterFragment flutterFragment = FlutterFragment.withNewEngine()
.initialRoute("/my_route")
.build();
引擎配置
// 使用缓存的引擎
FlutterFragment flutterFragment = FlutterFragment.withCachedEngine("my_engine_id")
.build();
// 使用新引擎
FlutterFragment flutterFragment = FlutterFragment.withNewEngine()
.dartEntrypoint("myCustomEntrypoint")
.initialRoute("/my_route")
.build();
渲染模式和透明度
// 设置渲染模式为纹理视图(默认)
FlutterFragment flutterFragment = FlutterFragment.withNewEngine()
.renderMode(RenderMode.texture) // 设置渲染模式为纹理视图(默认)
.renderMode(RenderMode.surface) //设置渲染模式为表面视图
.transparencyMode(TransparencyMode.transparent) //设置透明背景
.build();
添加到 Activity
// 在 Activity 中添加 FlutterFragment
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, flutterFragment)
.commit();
方法调用
// 获取 FlutterEngine
FlutterEngine flutterEngine = FlutterEngineCache.getInstance().get("my_engine_id");
// 设置方法调用处理器
flutterEngine.getDartExecutor().setMethodCallHandler((call, result) -> {
if (call.method.equals("getBatteryLevel")) {
int batteryLevel = getBatteryLevel();
result.success(batteryLevel);
} else {
result.notImplemented();
}
});
平台通道
// 在 FlutterFragment 中设置平台通道
new MethodChannel(flutterEngine.getDartExecutor(), "samples.flutter.dev/battery")
.setMethodCallHandler((call, result) -> {
// 处理来自 Flutter 的调用
});
实例:
缓存引擎一般在App种初始化
// 1. 预先缓存引擎 , flutterEngine也可以指定route和dartEntrypoint
FlutterEngine flutterEngine = new FlutterEngine(context);
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
FlutterEngineCache.getInstance().put("my_engine", flutterEngine);
// 2. 创建 Fragment
FlutterFragment flutterFragment = FlutterFragment.withCachedEngine("my_engine")
.initialRoute("/settings") //路由
.dartEntrypoint("customMain") //入口
.renderMode(RenderMode.texture)
.transparencyMode(TransparencyMode.transparent)
.shouldAttachEngineToActivity(true)
.build();
// 3. 添加 Fragment 到 Activity
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, flutterFragment)
.commit();
flutter文件:
1、route配置:
MaterialApp(
initialRoute: '/settings', // 与 Java 中的 initialRoute 对应
routes: {
'/settings': (context) => SettingsScreen(),
// 其他路由...
},
);
2、如果你指定了 customMain,需要在 lib/main.dart 或其他 Dart 文件中定义这个函数:
// 自定义入口函数
@pragma('vm:entry-point') // 确保不会被 Tree Shaking 移除
void customMain() {
runApp(MyApp()); // 启动 Flutter 应用
}
如果不使用lib/main.dart文件,比如lib/mytest.dart,具体调用如下:
// lib/mytest.dart
import 'package:flutter/material.dart';
// 自定义入口函数(必须添加 @pragma 注解)
@pragma('vm:entry-point')
void customMain() {
runApp(MyCustomApp()); // 启动你的 Flutter 应用
}
class MyCustomApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/settings', // 与 Java 代码中的 initialRoute 对应
routes: {
'/settings': (context) => SettingsScreen(), // 你的设置页面
},
);
}
}
class SettingsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Settings')),
body: Center(child: Text('This is the Settings Screen')),
);
}
}
Java调用:
// 在初始化使用自定义入口
FlutterEngine flutterEngine = new FlutterEngine(context);
flutterEngine.getDartExecutor().executeDartEntrypoint(
new DartExecutor.DartEntrypoint(
"lib/mytest.dart", // 指定 Dart 文件路径
"customMain" // 指定入口函数
)
);
// 缓存引擎
FlutterEngineCache.getInstance().put("my_engine", flutterEngine);
// 创建 Fragment
FlutterFragment flutterFragment = FlutterFragment.withCachedEngine("my_engine")
.initialRoute("/settings")
.dartEntrypoint("customMain")
.build();
FlutterFragment MethodChannel 双向(Android和Flutter)数据交互通信:
//Java代码
public class MainActivity extends AppCompatActivity {
private static final String CHANNEL = "channel_name";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FlutterFragment flutterFragment = FlutterFragment.withNewEngine()
.initialRoute("/")
.build();
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, flutterFragment)
.commit();
flutterFragment.getFlutterEngine().addEngineLifecycleListener(new FlutterEngine.EngineLifecycleListener() {
@Override
public void onPreEngineRestart() {}
@Override
public void onEngineWillDestroy() {}
@Override
public void onEngineCreated(@NonNull FlutterEngine flutterEngine) {
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler((call, result) -> {
if (call.method.equals("getBatteryLevel")) {
int batteryLevel = getBatteryLevel();
result.success(batteryLevel);
} else {
result.notImplemented();
}
});
// 调用 Flutter 方法
new Handler().postDelayed(() -> {
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.invokeMethod("showMessage", "Hello from Android", new MethodChannel.Result() {
@Override
public void success(Object o) {
Log.d("MainActivity", "Flutter responded: " + o);
}
// 其他回调方法...
});
}, 3000);
}
});
}
private int getBatteryLevel() {
// 实现获取电池电量的逻辑
return 50; // 示例值
}
}
Flutter代码:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State
static const MethodChannel _channel = MethodChannel('channel_name');
String _message = 'No message yet';
int _batteryLevel = 0;
@override
void initState() {
super.initState();
_setupMethodChannel();
_getBatteryLevel();
}
void _setupMethodChannel() {
_channel.setMethodCallHandler((MethodCall call) async {
switch (call.method) {
case 'showMessage':
setState(() {
_message = call.arguments;
});
return 'Message received in Flutter';
default:
throw MissingPluginException('Not Implemented');
}
});
}
Future
try {
final int result = await _channel.invokeMethod('getBatteryLevel');
setState(() {
_batteryLevel = result;
});
} on PlatformException catch (e) {
setState(() {
_batteryLevel = -1;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('FlutterFragment Communication')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Battery Level: $_batteryLevel%'),
SizedBox(height: 20),
Text('Message from Native: $_message'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _getBatteryLevel,
child: Text('Refresh Battery Level'),
),
],
),
),
);
}
}