My native library has a function that takes a closure parameter. This closure is necessary to ensure that network access is complete (the http request is non-blocking) so that the closure can take certain actions. Because Flutter plugin functions cannot take closures, I have to make this native function return a value. But because of the time issue, it cannot return the correct value back to the dart part of the code. Is there a good solution to this?
Asked
Active
Viewed 63 times
0
-
It would be perfectly reasonable to define a Native->Dart function that is called when your native activity ends. You could use the Dart callback to complete a Future. Also note that, on Android at least, it's allowed to call `result.success` in the native completion method. – Richard Heap Jul 12 '22 at 22:11
-
(Note that, if your completion happens on another thread, then you need to post to the main looper.) – Richard Heap Jul 12 '22 at 22:33
-
@RichardHeap When you said Native -> Dart function, is it still a function inside the class that implements FlutterPlugin? If so, do I create a function that satisfies the requirement of the native function? As an example for the iOS inside the handleMethodCall, I can do this: [MyPlugin loginWithId:userName password:password completion:loginResult] – Wei Wen Jul 13 '22 at 02:17
-
Sorry the above is not quite right. What I meant is: [MyNativeClass loginWithId:userName password:password completion:loginResult]. loginResult is a function created in the plugin class to satisfy the requirement of the native function, i.e. taking a BOOL parameter and returns nothing. If I put the above code inside result(), it does not return anything to the Dart part of the plugin. So it is still not useful. All I want is to be able to return wether login is successful or not since it is not possible to pass function parameter from the Dart code. Could you provide more details? Thank you! – Wei Wen Jul 13 '22 at 02:27
-
Since loginResult is inside the native implementation, it is also an objective c function. I am sure this is not what you meant by Native -> Dart function. – Wei Wen Jul 13 '22 at 02:29
-
It seems that you are not aware that method channels are bidirectional. Not only can you call native functions from Dart (that's what you are already doing), but you can call Dart functions from native. So, one strategy might be to call from native to Dart to start the login process (returning whatever you like, but obviously not the login result, as you don't have that yet). Then in your native closure, where you get the actual result, invoke a method that calls Dart, passing the login result. – Richard Heap Jul 13 '22 at 09:52
-
See this sample code for an example of calling to Dart https://github.com/richardheap/audio_worklet/blob/master/android/src/main/java/io/swhh/audio_worklet/AudioWorkletHelper.java – Richard Heap Jul 13 '22 at 09:52
-
@RichardHeap I saw your sample code. Thank you! But I think what I wanted to do is a bit different. Initially if Flutter plugin allowed callback functions, what I wanted to do is to pass the callback function which contained code to go to details page if successful, otherwise display alert. All these are in the callback function. Invoking the login starts from the dart part, not from the native part. The dart part passes the message to the channel which then invokes the native code's login function. The native code has a callback which initially was to achieve what I said above in dart code. – Wei Wen Jul 14 '22 at 03:24
-
I can add a native function that actually calls another dart function (to be added). This native function is passed to the login function as the callback. But what I don't understand is the the result of dart function (to be added) is not going anywhere. I still want to get the result of the dart plugin's result (the one that is exposed to the user). – Wei Wen Jul 14 '22 at 03:27
-
The callback I initially wanted to use in the plugin function is for the plugin users to fill in. They can put whatever they want in the callback function based on the login being successful or not. What I said above about showing details page or alert is just an example of what the users may want to do. – Wei Wen Jul 14 '22 at 03:37
-
Check out: https://stackoverflow.com/questions/70370222/why-does-methodchannel-result-success-sometimes-cause-a-timeout-at-flutter. Ignore the timeout issue, that's not important to you. Concentrate instead on how the native function holds onto `result` and doesn't call `success` until the long-running native operation finishes. (Note how it calls `success` through the main looper handler.) – Richard Heap Jul 14 '22 at 11:38
1 Answers
0
I was able to solve the time issue by doing this inside the native implementation:
[MyNativeClass loginWithId:userName password:password completion:^(BOOL success) {
result([NSNumber numberWithBool:success]);
}];
Thanks to Richard Heap whose comments made me realize I can do it this way.

Wei Wen
- 133
- 1
- 9