我正在调用一个原生SDK,它会关闭并执行一些API调用,这显然是有时间限制的工作。在这项工作的90%中,我使用双向的回调和方法通道调用,这样Dart就可以调用Swift,Swift可以在完成后调用Dart。
我遇到的问题是当我希望同步等待API响应(或超时(时。
我运行了一些测试,因为我本来打算推迟发送回FlutterResult
,直到Swift回调被击中,但这严重地减慢了UI的速度,因为我相信所有平台调用都是在UI线程上进行的。我模拟了10秒的响应时间,应用程序在再次响应之前会完全挂起好几秒钟,如果我发送了一些这样的请求,应用程序会挂起10秒以上。
我对运行同步平台代码的最佳方式有点困惑,因为我认为平台代码不能从隔离中调用。
我想
- 获取用户详细信息
- 用户按下按钮
- 等待时显示动画
- 获得回应并继续前进
等待时表演动画当然是让人头疼的部分。我也不完全确定为什么,因为运行普通CPU工作——无论是原生CPU还是飞镖CPU——都不应该冻结渲染引擎?
无论如何,我唯一能想到的就是:
- Dart调用平台方法A
- 将标志
AwaitingMethodA
设置为true - 立即返回FlutterResult,但在Swift中设置回调
while (AwaitingMethodA)....
- 当Swift中的回调命中时,跳上UI线程并将消息发送回Dart,表示完成,这将AwaitingMethodA设置为false
- Dart代码继续
^,如果需要,我可以为上面的设置一个超时计时器来打破循环。
这种方法有什么问题吗,或者对于同步、有时限的平台工作有更好的约定吗?
不要在while循环中等待-这就是问题所在。
您应该使用Completer类(https://api.flutter.dev/flutter/dart-async/Completer-class.html)。正如文档所说,使用Completer,您可以轻松地将基于回调的api转换为基于未来的api。
你的代码可能是这样的:
class SdkResultType {
//let's assume this is the type that Sdk will return
}
class MyClass {
Completer _completer;
Future<SdkResultType> callSdk() {
_completer=Completer();
///this is where you would call the SDK
somehowCallTheSDK();
// this is where your code will wait
return _completer.future;
}
// your SDK callback - SDK should call this when completed
void sdkCallback(SdkResultType sdkResult) {
if (!_completer.isCompleted) {
//this is where you complete the _completer.future, unblocking your mainSdkCall function.
_completer.complete(sdkResult);
}
}
void mainSdkCall() async {
//this is whare you wait
var sdkResult=await callSdk();
// do the rest here
}
}