从Flutter中的Isolate监听方法调用UI方法会引发异常

时间:2019-12-04 07:22:26

标签: flutter dart download progress-bar dart-isolates

我尝试使用ovprogresshud(https://pub.dev/packages/ovprogresshud)来显示下载进度。我使用flutter_downloader(https://pub.dev/packages/flutter_downloader)进行下载。

我尝试通过隔离更新进度,但收到错误消息。 (如果我直接在我的代码中调用Progresshud.showWithStatus,请说在下载前说是可行的)

我的代码:

ReceivePort _port = ReceivePort();
...

IsolateNameServer.registerPortWithName(
        _port.sendPort, 'downloader_send_port');
_port.listen(
      (dynamic data) {
        String id = data[0];
        DownloadTaskStatus status = data[1];
        int progress = data[2];
        if (status == DownloadTaskStatus.complete) {
        } else if (status == DownloadTaskStatus.running) {
          Progresshud.showWithStatus("%$progress Downloaded");
        }
      },
      onDone: () {
        checkIfDictionaryUnzipped(DBFilePath);
      },
      onError: (error) {},
    );

我收到的错误:

Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'android.view.ViewParent android.view.ViewGroup.getParent()' on a null object reference, null)
E/flutter (29114): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:569:7)
E/flutter (29114): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:321:33)
E/flutter (29114): <asynchronous suspension>
E/flutter (29114): #2      Progresshud.showWithStatus (package:ovprogresshud/progresshud.dart:18:27)
E/flutter (29114): <asynchronous suspension>
....

2 个答案:

答案 0 :(得分:1)

检查重要提示here

  

重要说明:您的UI在主隔离图中呈现,而下载事件来自后台隔离(换句话说,回调中的代码在后台隔离中运行),因此您必须处理两个隔离之间的通信。

检查示例,

ReceivePort _port = ReceivePort();

@override
void initState() {
    super.initState();

    IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
    _port.listen((dynamic data) {
        String id = data[0];
        DownloadTaskStatus status = data[1];
        int progress = data[2];
        setState((){ });
    });

    FlutterDownloader.registerCallback(downloadCallback);
}

@override
void dispose() {
    IsolateNameServer.removePortNameMapping('downloader_send_port');
    super.dispose();
}

static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
    final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port');
    send.send([id, status, progress]);
}

答案 1 :(得分:0)

也许您可以使用带有异步功能的计算