前言
Flutter
是Google
开源的构建用户界面(UI
)工具包,帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web
、桌面和嵌入式平台。Flutter
开源、免费,拥有宽松的开源协议,适合商业项目。目前,Flutter
已推出稳定的2.0版本。也是目前最火的跨平台开发工具之一
创建AndroidView
将Flutter
中的Android
项目使用AndroidStudio
打开,然后在app
的包名下新建一个View
实现io.flutter.plugin.platform.PlatformView
接口,使用PlatformView
就可以将AndroidView
嵌入到Flutter
视图中去,由于需要进行视图对象创建所以在构造函数添加context
-
getView
返回你需要嵌入的AndroidView
-
dispose
调用此方法后,PlatformView
对象将不可用。调用此方法后,实现PlatformView
的插件必须清除对View
对象和PlatformView
的所有引用。 如果不这样做将导致内存泄漏。
import android.content.Context
import android.widget.TextView
import io.flutter.plugin.platform.PlatformView
class CustomerView(context: Context):PlatformView {
val textView: TextView = TextView(context).apply {
text = "Test View in Android "
}
override fun getView() = textView
override fun dispose() {
}
}
注册AndroidView
新建一个类继承自PlatformViewFactory
,在其中创建我们的View
import android.content.Context
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class CustomerViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE){
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
return CustomerView(context)
}
}
新建一个类继承自FlutterPlugin
import io.flutter.embedding.engine.plugins.FlutterPlugin
class CustomerViewPlugin : FlutterPlugin {
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
binding.platformViewRegistry.registerViewFactory("plugins.flutter.io/my_custom_platform_view",CustomerViewFactory())
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}
}
在MainActivity
中添加上述的Plugin
,registerViewFactory
中的viewTypeId
参数是一个唯一标识字符串,后续将引用在flutter
视图中
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine.plugins.add(CustomerViewPlugin())
}
}
在Flutter
中引用AndroidView
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: MyCustomerPlatformView(), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class MyCustomerPlatformView extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(viewType: ("plugins.flutter.io/my_custom_platform_view"));
} else {
return Text("No support this View");
}
}
}
Flutter与原生之间相互交互
上述案例中我们只是简单地额嵌入了一个原生View
,这种只适用于一个静态页面的处理,如果需要页面之间动态交互,则需要添加一些额外的配置,交互无非就是你可以调用我的功能,我可以调用你的功能
MethodChannel
用于两端的相互调用,并且可以返回结果,Native
调用Flutter
时需要在主线程中进行
Flutter
发送数据/调用Native
端
- 在Flutter中创建
MethodChannel
var channel = MethodChannel("samples.flutter.dev/callNative");
2.在Flutter中通过channel
发送数据给到Native
,通过invokeMethod
函数发送到Native
,然后当返回信息时将其进行显示
Container(
alignment: Alignment.center,
child: GestureDetector(
child: Text('Click to call Native'),
onTap: () async {
String result = await channel.invokeMethod("callNative", {"id": "1", "value": "Mike"});
showDialog(context: context, builder: (context){
return AlertDialog(title: Text("提示"),content: Text(result));
}
);
},
),
)
3.在Android
中定义相关的接受,onMethodCall
可以接受到此channel
对应的调用,两端之间channel
之间的关联是通过name
,也就是这里给的samples.flutter.dev/NativeChannel
,result.success()
是本次调用反馈的结果
class NativeMethodChannel(messenger: BinaryMessenger) : MethodChannel.MethodCallHandler {
val channel = MethodChannel(messenger, "samples.flutter.dev/NativeChannel")
init {
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "callNative") {
val value = call.argument("value")
result.success("Received it: value is $value")
}
}
}
4.在Native
的MainActivity
中对NativeMethodChannel
进行注册,这样它才会持续监听
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
NativeMethodChannel(flutterEngine.dartExecutor.binaryMessenger)
}
Android
发送数据/调用Flutter
端
Android
端
channel.invokeMethod("callFlutter","张三",object:MethodChannel.Result{
override fun success(result: Any?) {
Log.e("Mike","result $result")
}
override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
}
override fun notImplemented() {
}
})
Flutter
端接收
@override
void initState() {
super.initState();
channel.setMethodCallHandler((call) {
print("flutter called by native ${call.arguments}");
return Future.value("res");
});
}
BasicMessageChannel
EventChannel
他们的功能以及使用方式与MethodChannel
相似
MethodChannel,BasicMessageChannel,EventChannel的区别与选择
-
MethodChannel
使用异步的方式与原生进行交流,用于比如需要调用原生的某些功能,但是原生需要耗时返回的情况,这种事有返回值的调用,支持数据双向传递 -
EventChannel
是用来返回监听各个阶段的状态,没有返回值,并且只支持单向,只支持原生传递数据给Flutter
,可以用来监听某些特殊原生功能的状态 -
BasicMessageChannel
用于传递字符串和半结构化的消息
欢迎关注Mike的
Android 知识整理