为了实现Flutter与原生之间的数据传递,Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)。宿主监听的平台通道,并接收该消息。
Flutter定义了三种不同类型的Channel:
BasicMessageChannel:用于传递字符串和半结构化信息,持续通信,收到消息后可以回复
MethodChannel:用于传递方法调用(method invocation),一次性通信
EventChannel:用于数据流(event streams)通信,持续通信,收到消息后无法回复。
这三种类型的Channel都是全双工通信,即Dart端可以主动发送消息给platform端;同样,platform端也可以主动发送消息给Dart端
一、BasicMessageChannel用法
1、Dart端到Native端
Dart端代码:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MyBasicMessageChannel extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
routes: <String, WidgetBuilder>{
'home': (BuildContext context) => BasicMessageChannelHome(),
'second': (BuildContext context) => BasicMessageChannelSecond()
},
home: BasicMessageChannelHome (),
);
}
}
class BasicMessageChannelHome extends StatefulWidget {
State<BasicMessageChannelHome> createState() =>
BasicMessageChannelHomeState();
}
class BasicMessageChannelHomeState extends State<BasicMessageChannelHome> {
var _basicMessage = BasicMessageChannel("BasicChannel", StringCodec());
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: GestureDetector(
child: Text('发送BasicMessageChannel'),
onTap: () {
_basicMessage.send('JumpNativeActivity').then((value) {
print(value);
});
},
),
),
),
);
}
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_basicMessage.setMessageHandler((message) async {
print(message);
return 'ACK FROM ART';
});
});
}
}
Native端代码
package com.example.flutter_hello
import android.content.Context
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.StringCodec
const val TAG:String="MainActivity"
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
var channel = BasicMessageChannel(
flutterEngine.dartExecutor.binaryMessenger,
"BasicChannel",
StringCodec.INSTANCE
)
channel.setMessageHandler { message, reply ->
android.util.Log.e(TAG,message)
reply.reply("成功跳转")
}
}
}
二、MethodChannel用法
Dart端代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FlutterMethodChannel extends StatelessWidget {
MethodChannel methodChannel = MethodChannel('nativeCall');
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: GestureDetector(
onTap: () {
_callNativeMethod();
},
child: Center(
child: Text('调用Native方法'),
),
),
),
);
}
void _callNativeMethod() async {
try {
methodChannel.invokeMethod('nativeMethod');
} catch (e) {
print(e);
}
}
}
Native端代码
package com.example.flutter_hello
import android.content.Context
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StringCodec
var INIT_PARAMS = "initParams"
const val TAG:String="MainActivity"
class MainActivity : FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.e(TAG,"onCreate")
MethodChannel(
flutterEngine!!.dartExecutor.binaryMessenger,
"nativeCall"
).setMethodCallHandler { call, result ->
run {
if (call.method.equals("nativeMethod")) {
result.success("success")
Log.e(TAG, "Get Dart call method")
}
}
}
}
三、EventChannel用法
该示例是Native端实时把网络连接状态发送给Dart端
Dart端代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class FlutterEventChannel extends StatefulWidget{
State<FlutterEventChannel> createState() => _FlutterEventChannelState();
}
class _FlutterEventChannelState extends State<FlutterEventChannel> {
EventChannel eventChannel=EventChannel('getNetworkState');
String networkState="";
StreamSubscription? subscription;
void initState() {
super.initState();
subscription=eventChannel.receiveBroadcastStream().listen((event) {
_handleEvent(event);
});
}
void dispose() {
super.dispose();
subscription!.cancel();
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text('使用EventChannel:${networkState}'),
),
),
);
}
void _handleEvent(int event) {
setState(() {
if(event==0){
networkState="网络断开";
}else{
networkState="网络连接";
}
});
}
}
Native端
采用单例模式,保存EventSink用来发送数据
package com.example.flutter_hello
import io.flutter.plugin.common.EventChannel
class GloableEventChannel {
var eventSink: EventChannel.EventSink? = null
private object Holder{
val instance=GloableEventChannel()
}
companion object{
fun getInstance()=Holder.instance
}
}
网络广播接收者
package com.example.flutter_hello
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Build
import android.widget.Toast
import androidx.annotation.Nullable
import io.flutter.plugin.common.EventChannel
class NetWorkStateReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
//检测API是不是小于21,因为到了API21之后getNetworkInfo(int networkType)方法被弃用
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
//获得ConnectivityManager对象
val connMgr =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
//获取ConnectivityManager对象对应的NetworkInfo对象
//获取WIFI连接的信息
val wifiNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
//获取移动数据连接的信息
val dataNetworkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
if (GloableEventChannel.getInstance().eventSink==null){
return
}
if (wifiNetworkInfo!!.isConnected && dataNetworkInfo!!.isConnected) {
GloableEventChannel.getInstance().eventSink!!.success(1)
} else if (wifiNetworkInfo!!.isConnected && !dataNetworkInfo!!.isConnected) {
GloableEventChannel.getInstance().eventSink!!.success(0)
} else if (!wifiNetworkInfo!!.isConnected && dataNetworkInfo!!.isConnected) {
GloableEventChannel.getInstance().eventSink!!.success(1)
} else {
GloableEventChannel.getInstance().eventSink!!.success(0)
}
} else {
//获得ConnectivityManager对象
val connMgr =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
var connectedState = false
//获取所有网络连接的信息
val networks = connMgr.allNetworks
//通过循环将网络信息逐个取出来
for (i in networks.indices) {
//获取ConnectivityManager对象对应的NetworkInfo对象
val networkInfo = connMgr.getNetworkInfo(networks[i])
if (networkInfo!!.isAvailable && networkInfo!!.isConnected) {
connectedState = true
break
}
}
if (GloableEventChannel.getInstance().eventSink==null){
return
}
GloableEventChannel.getInstance().eventSink!!.success(if (connectedState) 1 else 0)
}
}
}
注册网络状态广播
package com.example.flutter_hello
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.os.Bundle
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.StringCodec
const val TAG:String="MainActivity"
class MainActivity : FlutterActivity() {
private lateinit var eventChannel:EventChannel
private lateinit var networkIntentFilter:IntentFilter
private val netWorkStateReceiver=NetWorkStateReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.e(TAG,"onCreate")
networkIntentFilter=IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
registerReceiver(netWorkStateReceiver,networkIntentFilter)
eventChannel= EventChannel(flutterEngine!!.dartExecutor.binaryMessenger,"getNetworkState")
eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
if (events != null) {
GloableEventChannel.getInstance().eventSink=events
}
}
override fun onCancel(arguments: Any?) {
}
})
}
override fun onDestroy() {
super.onDestroy()
Log.e(TAG,"onDestroy")
unregisterReceiver(netWorkStateReceiver)
}
}