前言
Flutter
是Google
開(kāi)源的構(gòu)建用戶界面(UI
)工具包僧凰,幫助開(kāi)發(fā)者通過(guò)一套代碼庫(kù)高效構(gòu)建多平臺(tái)精美應(yīng)用,支持移動(dòng)继效、Web
症杏、桌面和嵌入式平臺(tái)。Flutter
開(kāi)源瑞信、免費(fèi)厉颤,擁有寬松的開(kāi)源協(xié)議,適合商業(yè)項(xiàng)目凡简。目前逼友,Flutter
已推出穩(wěn)定的2.0版本精肃。也是目前最火的跨平臺(tái)開(kāi)發(fā)工具之一
創(chuàng)建AndroidView
將Flutter
中的Android
項(xiàng)目使用AndroidStudio
打開(kāi),然后在app
的包名下新建一個(gè)View
實(shí)現(xiàn)io.flutter.plugin.platform.PlatformView
接口帜乞,使用PlatformView
就可以將AndroidView
嵌入到Flutter
視圖中去司抱,由于需要進(jìn)行視圖對(duì)象創(chuàng)建所以在構(gòu)造函數(shù)添加context
-
getView
返回你需要嵌入的AndroidView
-
dispose
調(diào)用此方法后,PlatformView
對(duì)象將不可用黎烈。調(diào)用此方法后习柠,實(shí)現(xiàn)PlatformView
的插件必須清除對(duì)View
對(duì)象和PlatformView
的所有引用。 如果不這樣做將導(dǎo)致內(nèi)存泄漏照棋。
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() {
}
}
注冊(cè)AndroidView
新建一個(gè)類繼承自PlatformViewFactory
资溃,在其中創(chuàng)建我們的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)
}
}
新建一個(gè)類繼承自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
參數(shù)是一個(gè)唯一標(biāo)識(shí)字符串,后續(xù)將引用在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<MyHomePage> {
@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與原生之間相互交互
上述案例中我們只是簡(jiǎn)單地額嵌入了一個(gè)原生View
必怜,這種只適用于一個(gè)靜態(tài)頁(yè)面的處理肉拓,如果需要頁(yè)面之間動(dòng)態(tài)交互,則需要添加一些額外的配置梳庆,交互無(wú)非就是你可以調(diào)用我的功能暖途,我可以調(diào)用你的功能
MethodChannel
用于兩端的相互調(diào)用,并且可以返回結(jié)果膏执,Native
調(diào)用Flutter
時(shí)需要在主線程中進(jìn)行
Flutter
發(fā)送數(shù)據(jù)/調(diào)用Native
端
- 在Flutter中創(chuàng)建
MethodChannel
var channel = MethodChannel("samples.flutter.dev/callNative");
2.在Flutter中通過(guò)channel
發(fā)送數(shù)據(jù)給到Native
驻售,通過(guò)invokeMethod
函數(shù)發(fā)送到Native
,然后當(dāng)返回信息時(shí)將其進(jìn)行顯示
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
中定義相關(guān)的接受,onMethodCall
可以接受到此channel
對(duì)應(yīng)的調(diào)用,兩端之間channel
之間的關(guān)聯(lián)是通過(guò)name
,也就是這里給的samples.flutter.dev/NativeChannel
,result.success()
是本次調(diào)用反饋的結(jié)果
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<String>("value")
result.success("Received it: value is $value")
}
}
}
4.在Native
的MainActivity
中對(duì)NativeMethodChannel
進(jìn)行注冊(cè)更米,這樣它才會(huì)持續(xù)監(jiān)聽(tīng)
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
NativeMethodChannel(flutterEngine.dartExecutor.binaryMessenger)
}
Android
發(fā)送數(shù)據(jù)/調(diào)用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的區(qū)別與選擇
-
MethodChannel
使用異步的方式與原生進(jìn)行交流征峦,用于比如需要調(diào)用原生的某些功能迟几,但是原生需要耗時(shí)返回的情況,這種事有返回值的調(diào)用栏笆,支持?jǐn)?shù)據(jù)雙向傳遞 -
EventChannel
是用來(lái)返回監(jiān)聽(tīng)各個(gè)階段的狀態(tài)类腮,沒(méi)有返回值,并且只支持單向蛉加,只支持原生傳遞數(shù)據(jù)給Flutter
,可以用來(lái)監(jiān)聽(tīng)某些特殊原生功能的狀態(tài) -
BasicMessageChannel
用于傳遞字符串和半結(jié)構(gòu)化的消息
歡迎關(guān)注Mike的簡(jiǎn)書(shū)
Android 知識(shí)整理