Flutter 中的同步平台代码执行

时间:2021-03-30 09:41:12

标签: swift flutter dart flutter-method-channel

我正在调用一个本机 SDK,它会关闭并执行一些 API 调用,这显然是有时限的工作。对于这项工作的 90%,我使用双向回调和方法通道调用,因此 Dart 可以调用 Swift,然后 Swift 可以在完成后调用 Dart。

我遇到的问题是我希望同步等待 API 响应(或超时)。

我进行了一些测试,因为我原本打算推迟发送 FlutterResult 直到命中 Swift 回调,但是我相信这会严重减慢 UI所有平台调用都在 UI 线程上进行。我模拟了 10 秒的响应时间,应用会完全挂起好几秒钟,然后再次响应,如果我发送了一些这样的请求,应用会挂起 10 秒以上。

我对运行同步平台代码的最佳方式有些困惑,因为我认为平台代码不能从隔离中调用。

我想

  • 获取用户详细信息
  • 用户按下按钮
  • 等待时显示动画
  • 获得回应并继续前进。

在等待时显示动画当然是 janks 的一部分。我不完全确定为什么,因为无论是原生的还是 dart 运行通用 CPU 都应该不应该冻结渲染引擎?

无论如何,我唯一能想到的是:

  • Dart 调用平台方法 A
  • 将标志 AwaitingMethodA 设置为 true
  • 立即返回 FlutterResult 但在 Swift 中设置回调
  • while (AwaitingMethodA)....
  • 当 Swift 中的回调命中时,跳转到 UI 线程并向 Dart 发送消息说完成,这会将 AwaitingMethodA 设置为 false
  • Dart 代码继续......

^ 并且我可以为上述设置一个超时计时器以在必要时打破循环。

这种方法有什么问题吗,或者是否有更好的同步、有时间限制的平台工作约定?

1 个答案:

答案 0 :(得分:0)

不要在 while 循环中等待 - 这就是问题所在。

您应该使用 Completer 类 (https://api.flutter.dev/flutter/dart-async/Completer-class.html)。正如文档所说 - 使用 Completer,您可以轻松地将基于回调的 API 转换为基于未来的 API。

您的代码可能如下所示:

public class SQLParser {

    public static void main(String args[]) {

    String sqlString = "select * from table t where columnA = 'hello' and columnB = 'hai'";
    Map<Integer,String> values = new HashMap<>();
    values = parseQuery(sqlString);
    System.out.println(values);   // prints  { {1,'hello'} , {2,'hai'} }
    }

    private static Map<Integer,String> parseQuery(String sqlString) {
        Map<Integer,String> values = new HashMap<>();
        //
        //  ????  I want this function 
        //
        return values;
        
    }

}