Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a solution to asynchronously wait for C++ data on Flutter's invokeMethod?

Tags:

c++

flutter

dart

Currently, this is how I read from C++ using Flutter:

final Uint8List result = await platform.invokeMethod(Common.MESSAGE_METHOD, {"message": buffer});

It is handled by Kotlin like this:

    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
        if (call.method == MESSAGE_METHOD) {
            val message: ByteArray? = call.argument<ByteArray>("message")
            //... //response = Read something FROM C++
            result.success(response)

Since this happens in the main thread, if I take too much time to answer, I make Flutter's UI slow.

Is there a solution to get C++ data in an async way?

I know that Flutter has support for event channels to send data back from C++ to Flutter. But what about just requesting the data on the Flutter side and waiting for it to arrive in a Future, so I can have lots of widgets inside a FutureBuilder that resolves to something when ready?

like image 446
Guerlando OCs Avatar asked Apr 10 '21 19:04

Guerlando OCs


2 Answers

If reading something from C++ is a heavy process, You can use AsysncTask to perform it in the background for android.

internal class HeavyMsgReader(var result: MethodChannel.Result) : AsyncTask<ByteArray?, Void?, String?>() {

    override fun doInBackground(vararg message: ByteArray?): String {
        //... //response = Read something FROM C++
        return "response"
    }

    override fun onPostExecute(response: String?) {
        result.success(response)
    }
}

Calling async task:

MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
        if (call.method == MESSAGE_METHOD) {
            val message: ByteArray? = call.argument<ByteArray>("message")
            HeavyMsgReader(result).execute(message);
like image 72
Ravi Sevta Avatar answered Oct 18 '22 20:10

Ravi Sevta


Hopefully this will work

import 'dart:async';

Future<Uint8List> fetchData(buffer) async {
  
  final Uint8List result = await platform.invokeMethod(Common.MESSAGE_METHOD, {"message": buffer});
    
  return result;
}

And just call it, like this

fetchData(buffer).then((result) => {
    print(result)
}).catchError(print);

Proof that its working:

import 'dart:async';

Future<String> fetchUserOrder() async {
      
  await Future.delayed(Duration(seconds: 5));
    
  return 'Callback!';
}

Future<void> main() async {
    
  fetchUserOrder().then((result) => {
    print(result)
  }).catchError(print);
  
  
  while(true){
    print('main_thread_running');
    await Future.delayed(Duration(seconds: 1));
  }
  
}

output:

main_thread_running
main_thread_running
main_thread_running
main_thread_running
main_thread_running
Callback!
main_thread_running
main_thread_running
...
like image 2
Ofekfarjun Avatar answered Oct 18 '22 20:10

Ofekfarjun