How to call methods in Dart portion of the app, from the native platform using MethodChannel?
I am writing a native plugin that, in some cases, has to call functions in the Flutter portion of the app, written in Dart. How it's achieved, is explained here: https://flutter.io/platform-channels/
Furthermore, an example of invoking a method from the native/platform part towards the Dart/non-native is here: https://github.com/flutter/plugins/tree/master/packages/quick_actions
Now, this example is really nice in case the platform only needs to invoke a method
, i.e. that call returns nothing/void
, but in case it needs to invoke a function
, i.e. needs a return value from the non-native/Dart part, I could not have found an example or documentation on the internet. I believe it can be implemented though, because in the native Java part, there is a method:
public void invokeMethod(String method, Object arguments, MethodChannel.Result callback)
So, there is a callback
object that could have a return value from the non-native part - or, I am mistaken here, and there is currently no way of returning a value from the non-native Dart portion of the app?
The signature is void setMethodCallHandler(Future<dynamic> handler(MethodCall call))
, so we need to provide a function at the Dart end that returns Future<dynamic>
, for example _channel.setMethodCallHandler(myUtilsHandler);
Then implement the handler. This one handles two methods foo
and bar
returning respectively String
and double
.
Future<dynamic> myUtilsHandler(MethodCall methodCall) async {
switch (methodCall.method) {
case 'foo':
return 'some string';
case 'bar':
return 123.0;
default:
throw MissingPluginException('notImplemented');
}
}
At the Java end the return value is passed to the success
method of the Result
callback.
channel.invokeMethod("foo", arguments, new Result() {
@Override
public void success(Object o) {
// this will be called with o = "some string"
}
@Override
public void error(String s, String s1, Object o) {}
@Override
public void notImplemented() {}
});
In Swift, the return value is an Any?
passed to the result
closure. (Not implemented is signaled by the any parameter being the const NSObject
value FlutterMethodNotImplemented
.)
channel.invokeMethod("foo", arguments: args, result: {(r:Any?) -> () in
// this will be called with r = "some string" (or FlutterMethodNotImplemented)
})