Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 如何在执行invokeMethod()时侦听异步响应?_Flutter_Dart - Fatal编程技术网

Flutter 如何在执行invokeMethod()时侦听异步响应?

Flutter 如何在执行invokeMethod()时侦听异步响应?,flutter,dart,Flutter,Dart,我正在开发一个小的颤振应用程序,我使用一个本地库进行一些计算。dart和java(在android上)之间的通信是双向的,并使用MethodChannel实现。 我从dart调用_channel.invokeMethod(“someJavaMethod”)中的wait来开始计算。这将从Java触发本机库的初始化。此初始化的结果作为异步JNI调用返回,然后触发out_channel.invokeMethod(“someDartMethod”) 我的计划是将out_频道绑定到本地dart广播流,这样

我正在开发一个小的颤振应用程序,我使用一个本地库进行一些计算。dart和java(在android上)之间的通信是双向的,并使用MethodChannel实现。 我从dart调用_channel.invokeMethod(“someJavaMethod”)中的wait来开始计算。这将从Java触发本机库的初始化。此初始化的结果作为异步JNI调用返回,然后触发out_channel.invokeMethod(“someDartMethod”)

我的计划是将out_频道绑定到本地dart广播流,这样我就可以调用someJavaMethod,然后等待myMethodStream

问题是“someDartMethod”可能在“someJavaMethod”调用返回之前出现

我拥有的组合代码示例:

    static const MethodChannel _channel_in = const 
    MethodChannel('native_lib_wrapper_out'); 
    static const MethodChannel _channel_out = const 
    MethodChannel('native_lib_wrapper_in');
    final StreamController<MethodCall> _methodStreamController = new 
    StreamController.broadcast();

    NativeLibWrapper._() {
          _channel_in.setMethodCallHandler((MethodCall call) {
              _methodStreamController.add(call);
              return;
         });
    }


    Future<Map<dynamic,dynamic>> initLib(String id, String filePath) 
      async {
        Map<dynamic,dynamic> ret;

        ret = await _channel_out.invokeMethod("initLib",  <String, 
        dynamic> { // data to be passed to the function
                    'id': id,
                    'filePath': filePath,
                  });
        print('initLib - invokeMethod done. wait for stream');
        if(ret["status"] == 0) {
          await NativeLibWrapper.instance._methodStream
                .where((m) => m.method == "libInitEnded")
                .map((m){
                    var args = m.arguments;
                    ret = args;
                  }).first;
        }
        return ret;
    }
static const MethodChannel\u channel\u in=const
MethodChannel('native_lib_wrapper_out');
静态常量方法通道_通道_输出=常量
MethodChannel('native_lib_wrapper_in');
最终StreamController _methodStreamController=新
StreamController.broadcast();
NativeLibWrapper.(){
_setMethodCallHandler((MethodCall调用)中的通道_{
_methodStreamController.add(调用);
返回;
});
}
Future initLib(字符串id、字符串文件路径)
异步的{
地图检索;
ret=wait _channel _out.invokeMethod(“initLib”),{//要传递给函数的数据
“id”:id,
“文件路径”:文件路径,
});
打印('initLib-invokeMethod done.wait for stream');
如果(ret[“状态”]==0){
等待NativeLibWrapper.instance.\u methodStream
其中((m)=>m.method==“libinitend”)
.map((m){
var args=m.arguments;
ret=args;
}).首先;
}
返回ret;
}
<>我希望代码能在我的流中获得方法调用LBIN,然后在那个点之后返回它,但是它一直挂在等待流上,从日志中看,在中间打印之前调用LiBiTeNebug。p> 那么,有没有更好的方法来构建这个?这将不是唯一来回的方法,所以我希望能得到一个很好的稳定解决方案。

一个通道

您应该只需要一个频道。不需要输入和输出通道。两端可以通过一个通道调用另一端的操作

只有一个UI线程

从Dart调用本机时,本机方法由本机UI线程处理。除非您使用的是线程池,否则这意味着Dart到本机方法是按顺序处理的。不等待每个本机方法的答案是没有意义的。或者,换句话说,同时启动两个本机方法没有意义,因为它们将由单个本机线程连续执行。(请注意,您不应该在本机线程上执行耗时的操作,因为这会干扰它所做的其他事情,如手势检测。)每个“省道到本机”方法都应该返回其结果

使用线程池

如果一次线程/单方法调用是不可接受的,请考虑本地端的线程池。现在您可以使用多个方法,因为有多个执行线程。现在,您应该像通过套接字与服务器通信一样设计呼叫/响应。客户端为每个请求提供一个“调用id”。每个方法只返回请求排队的布尔值。请求完成后,另一端调用“done”方法,传递原始id和结果。然后,调用方可以将响应id与请求id相匹配,并适当地处理响应(并取消为检测超时而启动的任何计时器)。请注意,响应可以以任何顺序到达,但通过id与它们的请求匹配


在Android上,必须在
UIThread
上调用本机到Dart方法。如果从工作线程调用“done”方法,则需要将
post
a
Runnable
lambda发送到主循环器。

提到的线程池是我最终希望通过此解决方案实现的,但实际上最后一段是解决问题的一段。结果表明,调用了本机到dart方法调用,但从未执行,因为它不在UI线程中。简单地把它放在UI线程上就解决了问题,我的初始代码按预期工作。谢谢你详尽的回答。链接到使用线程池的技术将非常有用,一个小示例将是最好的