本文基于Flutter 3.19.3版别进行开发
Flutter 3.19.3 • channel stable • github.com/flutter/flu…
Framework • revision ba39319843 (8 days ago) • 2024-03-07 15:22:21 -0600
Engine • revision 2e4ba9c6fb
Tools • Dart 3.3.1 • DevTools 2.31.1
本篇为Flutter基建的第十三篇文章,本篇文章首要介绍在Flutter中怎么经过插件的方式进行Android和iOS原生的交互操作,详细会分为两部分,其间一部分Flutter运用MethodChannel从原生端中获取信息,另一部分则是原生端经过EventChannel向Flutter端主动发送音讯,下面让咱们一同进入文章感触下吧~
Flutter基建系列文章
- Flutter基建 – Dart基础类型
- Flutter基建 – Dart办法和类
- Flutter基建 – 文本组件
- Flutter基建 – 按钮全解析
- Flutter基建 – 布局组件全面解析
- Flutter基建 – 离不开的列表组件
- Flutter基建 – 寸步不离的State**Widget
- Flutter基建 – 异步加载UI
- Flutter基建 – 12种隐式动画小组件全解析
- Flutter基建 – Hero动画有多英雄
- Flutter基建 – 状况办理State
- Flutter基建 – ChangeNotifier详解
- Flutter基建 – 运用插件和原生Android、iOS交互
运用MethodChannel获取音讯
MethodChannel首要作用便是Flutter层向原生层面获取音讯,原生层归于一个被迫的状况,当收到Flutter层传递获取的详细办法时,能够依据详细的办法和参数向Flutter层传递对应的音讯。下面咱们介绍MethodChannel的用法过程中,以获取Android和iOS体系版别为例,来直观的感触下MethodChannel的详细逻辑。
Flutter层界说MethodChannel
首要咱们在Flutter层面界说好MethodChannel目标,它需求接收一个name参数,这个参数仍是挺重要的,Flutter层和原生层便是经过name来匹配对应的通道。
class _MyHomePageState extends State<MyHomePage> {
final methodChannel = const MethodChannel("version_channel");
String _version = "";
@override
void initState() {
super.initState();
getVersion();
}
Future<void> getVersion() async {
String version = await methodChannel.invokeMethod("getVersion");
setState(() {
_version = version;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Version Info: $_version',
),
],
),
),
);
}
}
上述代码在第二行咱们进行了MethodChannel目标的界说,然后在initState()
办法中调用了一个getVersion()
办法,它内部便是经过MethodChannel来衔接原生层,经过对应的办法名来获取需求的信息,这儿需求留意的一点便是methodChannel.invokeMethod()
办法是一个异步函数,大家在调用的时候略微留意一下,加上await
等候即可。
methodChannel.invokeMethod()
办法除了传入办法名以外,还能够经过可选参数arguments来传入指定的参数,然后在原生层获取即可。
Flutter层界说好管道和调用的办法之后,咱们就能够在Android或许iOS原生层进行办法的详细完成了,接着咱们以Android端为例(由于手头没有ios设备…..)
Android端完成音讯传递
无论是Android端仍是iOS端,也仍是以MethodChannel为主,它能够协助咱们处理管道对应的办法,然后进行音讯传递。
class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
flutterEngine?.dartExecutor?.let {
MethodChannel(it, "version_channel").setMethodCallHandler { call, result ->
if (call.method == "getVersion") {
result.success("Android ${Build.VERSION.RELEASE}")
}
}
}
}
}
全体上来看,Android端的代码仍是比较简单的,经过创立一个MethodChannel目标,内部需求传入BinaryMessenger和name,这儿的BinaryMessenger能够经过flutterEngine获取到,然后name参数有必要和Flutter层保持一致,不然会提示找不到对应的MethodChannel。
界说好MethodChannel目标之后,直接调用它的setMethodCallHandler()
办法即可,在回调中能够经过call获取经过对应的办法名和参数等信息,详细如下:
回调的result能够协助咱们将对应的音讯传递给Flutter层,可运用result.success()
来传递正常的音讯,也能够经过result.error()
来通知Flutter层音讯传递失利。
这儿留意一下, 在写完Android端代码之后,记得保存一下,不然运转会不生效,不知道小伙伴会不会出现相同的问题,欢迎沟通交流~
最终咱们来运转看下效果:
运用EventChannel获取音讯
介绍完MethodChannel用法之后,咱们再来看下EventChannel的详细运用逻辑,它和MethodChannel最大的区别便是原生层在其间归于一个主动的角色,它能够自意向Flutter传递一些需求的音讯,当Flutter开始接收时,原生层就能够依据通道名来向此通道继续的发送音讯,下面咱们以定时器为例,完成一个Android端向Flutter层发送计时的一个小例子。
Flutter层界说EventChannel
直接上完好代码,后面咱们跟着代码一同了解下。
class _MyHomePageState extends State<MyHomePage> {
final eventChannel = const EventChannel("count_channel");
StreamSubscription? _streamSubscription;
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Count: $count'),
TextButton(
onPressed: () {
registerEventChannel();
},
child: const Text("注册EventChannel")),
TextButton(
onPressed: () {
unRegisterEventChannel();
},
child: const Text("解注册EventChannel")),
],
),
),
);
}
void registerEventChannel() {
_streamSubscription = eventChannel.receiveBroadcastStream().listen((event) {
setState(() {
count = event;
});
});
}
void unRegisterEventChannel() {
if (_streamSubscription != null) {
_streamSubscription!.cancel();
_streamSubscription = null;
}
}
@override
void dispose() {
super.dispose();
unRegisterEventChannel();
}
}
咱们先从第二行看,在这儿界说好了一个EventChannel目标,然后传入name参数,此name参数和MethodChannel作用一向,原生端要与其保持一致;
然后在下面第三行界说了一个StreamSubscription目标,它是EventChannel履行listen监听后发生的目标,可撤销和暂停监听操作;
然后在Widget中别离界说Text用于显现原生端传递过来的信息,两个TextButton别离用于履行注册监听和撤销监听;
在第34行的registerEventChannel()
办法中,调用EventChannel.receiveBroadcastStream().listen()
办法进行经过的监听,listen()
办法中一共有四个参数:
-
onData()
用于处理通道中传递过来的数据,这儿咱们直接将传递过来的count显现在界面上; -
onError()
用于处理通道中发生反常时场景; -
onDone()
办法则是表明通道被撤销监听或许原生端传递了done事件; -
cancelOnError
这个参数假如被赋值true之后,那么通道在发生反常时则会主动撤销监听。
接着在第42行unRegisterEventChannel()
办法中咱们进行了通道的撤销监听操作。
接下来咱们再来看看Android端是怎么继续发送数据的:
Android端继续发送音讯
class MainActivity : FlutterActivity() {
var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
flutterEngine?.dartExecutor?.let {
EventChannel(it, "count_channel").setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
thread {
while (count < 20) {
runOnUiThread { events?.success(count++) }
Thread.sleep(1000L)
}
}
}
override fun onCancel(arguments: Any?) {
Log.d("taonce", "EventChannel onCancel")
count = 0
}
})
}
}
}
其实在EventChannel的运用场景下,Android端的代码就略微要简单一点了,只需求经过EventChannel目标的setStreamHandler()
办法进行数据的传递即可,此办法需求传递一个EventChannel.StreamHandler回调,回调内部包含了onListen()
和onCancel()
办法,传递需求能够在onListen()
办法中处理,onCancel()
办法则是表明Flutter端进行了撤销操作。
这儿不得不提一下,在原生端发送数据时线程问题,这儿需求在主线程中进行events.success()
操作,不然就会发生Crash问题~
最终咱们来运转下程序看看详细效果:
当咱们在第11s时点击解注册按钮之后,Android端就会收到onCancel回调。
写在最终
本篇文章首要介绍了Flutter中MethodChannel和EventChannel的基本运用,在Flutter的日常开发中,这两个常识点在运用频率和重要性上都是等级比较高的,希望经过文章给阅览的小伙伴们带来一点协助,后续会按部就班逐渐接触Flutter更多的常识。
我是Taonce,假如觉得本文对你有所协助,帮忙关注、赞或许收藏三连一下,谢谢~