flutter DartPluginRegistrant.ensureInitialized未修复Isolate中path_provider的使用

ui7jx7zq  于 2023-05-23  发布在  Flutter
关注(0)|答案(1)|浏览(349)

尝试在Isolate中使用path_provider不起作用。
我已经遵循了this Flutter issue的建议。
WidgetsFlutterBinding.ensureInitialized()似乎没有按预期工作。

Flutter 3.3.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4f9d92fbbd (3 days ago) • 2022-09-06 17:54:53 -0700
Engine • revision 3efdf03e73
Tools • Dart 2.18.0 • DevTools 2.15.0

最小代码复制

import 'dart:isolate';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Isolate Test',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(title: 'Isolate Test'),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key, required this.title});

  final String title;

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _spawnIsolate(),
        tooltip: 'Spawn',
        child: const Icon(Icons.add_circle),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Future _spawnIsolate() async {
    final receivePort = ReceivePort();
    Isolate.spawn(isolateTestEntry, receivePort.sendPort);
  }
}

Future isolateTestEntry(SendPort sendPort) async {
  DartPluginRegistrant.ensureInitialized();
  final directory = await getApplicationDocumentsDirectory();
  debugPrint('directory path: ${directory.path}');
  Isolate.exit();
}
pubspec.yaml
name: isolate_test
description: Testing Isolate and path_provider

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: '>=2.18.0 <3.0.0'

dependencies:
  flutter:
    sdk: flutter

  path_provider: ^2.0.11
  cupertino_icons: ^1.0.5

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.1

flutter:
  uses-material-design: true

Logcat输出:

[ERROR:flutter/runtime/dart_isolate.cc(1098)] Unhandled exception:和随后的线在按压FAB之后出现。在运行Android 11的Pixel 2上进行了测试。

Launching lib\main.dart on Pixel 2 in debug mode...
Running Gradle task 'assembleDebug'...
√  Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Debug service listening on ws://127.0.0.1:51134/m0XeAfmtukY=/ws
Syncing files to device Pixel 2...
I/Gralloc4(15026): mapper 4.x is not supported
W/Gralloc3(15026): mapper 3.x is not supported
E/flutter (15026): [ERROR:flutter/runtime/dart_isolate.cc(1098)] Unhandled exception:
E/flutter (15026): Binding has not yet been initialized.
E/flutter (15026): The "instance" getter on the ServicesBinding binding mixin is only available once that binding has been initialized.
E/flutter (15026): Typically, this is done by calling "WidgetsFlutterBinding.ensureInitialized()" or "runApp()" (the latter calls the former). Typically this call is done in the "void main()" method. The "ensureInitialized" method is idempotent; calling it multiple times is not harmful. After calling that method, the "instance" getter will return the binding.
E/flutter (15026): In a test, one can call "TestWidgetsFlutterBinding.ensureInitialized()" as the first line in the test's "main()" method to initialize the binding.
E/flutter (15026): If ServicesBinding is a custom binding mixin, there must also be a custom binding class, like WidgetsFlutterBinding, but that mixes in the selected binding, and that is the class that must be constructed before using the "instance" getter.
E/flutter (15026): #0      BindingBase.checkInstance.<anonymous closure> (package:flutter/src/foundation/binding.dart:284:9)
E/flutter (15026): #1      BindingBase.checkInstance (package:flutter/src/foundation/binding.dart:366:6)
E/flutter (15026): #2      ServicesBinding.instance (package:flutter/src/services/binding.dart:54:54)
E/flutter (15026): #3      BasicMessageChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:166:45)
E/flutter (15026): #4      BasicMessageChannel.send (package:flutter/src/services/platform_channel.dart:180:38)
E/flutter (15026): #5      PathProviderApi.getApplicationDocumentsPath (package:path_provider_android/messages.g.dart:96:23)
E/flutter (15026): #6      PathProviderAndroid.getApplicationDocumentsPath (package:path_provider_android/path_provider_android.dart:62:17)
E/flutter (15026): #7      getApplicationDocumentsDirectory (package:path_provider/path_provider.dart:115:40)
E/flutter (15026): #8      isolateTestEntry (package:isolate_test/main.dart:60:27)
E/flutter (15026): #9      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:17)
E/flutter (15026): #10     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
k5hmc34c

k5hmc34c1#

在flutter 3.10.1中,初始化BackgroundIsolateBinaryMessenger允许我访问documents目录:

RootIsolateToken rootIsolateToken = RootIsolateToken.instance!;

[...]

Future isolateTestEntry(SendPort sendPort) async {
  BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
  final directory = await getApplicationDocumentsDirectory();
  debugPrint('directory path: ${directory.path}');
  Isolate.exit();
}

相关问题