大多数同学都知道Flutter与原生通信MethodChannel或者EventChannel。这两个Channel在我之前的文章中有讲到区别和共同点,我们知道本质上都是MethodChannel。
我们还知道,在开发插件的过程中,免不了要使用这两个哥们来帮我们进行原生与Flutter互通。
今天,我们遇到的问题是,我们一个纯粹的flutter工程,如果,需要在Flutter中调用原生,或者在原生中取调用到flutter中的代码,我们该如何做。
首先,我们来看第一个问题:
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "samples.flutter.io/battery";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getBatteryLevel")) {
int batteryLevel = getBatteryLevel();
if (batteryLevel != -1) {
result.success(batteryLevel);
} else {
result.error("UNAVAILABLE", "Battery level not available.", null);
}
} else {
result.notImplemented();
}
}
});
}
}
以上是官方给出的一个例子,我们在onMethodCall中实现需要的逻辑即可,所以,我们在flutter中就可以
// Get battery level.
String _batteryLevel = 'Unknown battery level.';
Future<Null> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
已这样的方式调用原生代码了。
那么有没有想过,为啥这样就可以使得Flutter调用原生了呢?
我们看一下MethodChannel的构造方法,第一个参数是一个BinaryMessenger,而,我们在原生中构造的那个MethodChannel
传入的第一个参数是getFlutterView,其实就是FlutterView了,看源码可以知道,FlutterView实际上是实现了BinaryMessenger
这个接口的。所以,沟通两者的桥梁就是这个BinaryMessenger了,话句话说,Flutter能和原生通信,纯属于BinaryMessenger
的功劳。
/**
* Creates a new channel associated with the specified {@link BinaryMessenger} and with the
* specified name and the standard {@link MethodCodec}.
*
* @param messenger a {@link BinaryMessenger}.
* @param name a channel name String.
*/
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
那么,反过来呢?
不用想,桥梁应该还是BinaryMessenger无疑,但是,这次有谁来搭这个通道呢?应该是Flutter端搭建这个通道,因为刚才Flutter调用原生的时候,是原生来准备这个调用环境的。因此。我们在Flutter端这么做。
MethodChannel methodChannel = new MethodChannel('intl:intl-globle-notify');
methodChannel.setMethodCallHandler((MethodCall call) async {
if (call.method == "onLoginSuccess") {
userInfoNotifier.getUserInfo();
} else if (call.method == "onAuthSuccess") {
userInfoNotifier.getUserInfo();
}
});
啦搭建这个通道,随后,在原生中,我们应该在哪里去连接上这个通道呢?
其实无所谓在哪里,只要你能找到这个BinaryMessenger即可,在哪里找呢,在MainActivity extends FlutterActivity 这个Activity的 configureFlutterEngine 方法中。
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
flutterEngine.getPlugins().add(new ITLoginPlugin());
methodChannel = new MethodChannel(flutterEngine.getDartExecutor(),"intl:intl-globle-notify");
}
为什么是这里,以为这里比较方便拿到 这个BinaryMesenger,如果你找到其他地方比较方便拿到这个BinaryMesenger,也可以在其他地方初始化。
有好事者(比如说我自己)就问了,这个BinaryMesenger是同一个的吗?从目前来看,是的。都应该是这个
BinaryMessenger get defaultBinaryMessenger {
assert(() {
if (ServicesBinding.instance == null) {
throw FlutterError(
'ServicesBinding.defaultBinaryMessenger was accessed before the '
'binding was initialized.\n'
"If you're running an application and need to access the binary "
'messenger before `runApp()` has been called (for example, during '
'plugin initialization), then you need to explicitly call the '
'`WidgetsFlutterBinding.ensureInitialized()` first.\n'
"If you're running a test, you can call the "
'`TestWidgetsFlutterBinding.ensureInitialized()` as the first line in '
"your test's `main()` method to initialize the binding."
);
}
return true;
}());
return ServicesBinding.instance.defaultBinaryMessenger;
}
所以,今天,我们就学会了:
1、如何在Flutter中调用原生代码。
2、如何在原生中调用Flutter代码。
总结一下,如果觉得业务逻辑有点多,完全可以将代码逻辑放在一个插件中。
flutterEngine.getPlugins().add(newITLoginPlugin());
类似于这样了,对于插件的编写,相信有一堆的文章知道你如何办。插件中,很显然通道的打通都是靠那个BinaryMessenger。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。