新进程或隔离中的flutter run firebase存储和firestore导致绑定问题

k5ifujac  于 2022-12-30  发布在  Flutter
关注(0)|答案(1)|浏览(104)

我建立了一个应用程序,用户上传一个标志,我已经激活了在Firebase存储的大小调整扩展。因此,所有上传的图像,将被替换为大小调整的图像与相同的参考,但以"_600x600.png"结束,而不是". png"。
考虑到在上传功能中,如果我等待原始文件上传,它不保证新的"600x600.png"完成上传。
我的最终目标是获得新文件的下载URL。我最好的方法是从客户端运行一个隔离函数,尝试获得新文件的路径,如果没有成功(因为上传调整大小的文件可能需要一段时间),它将等待1秒,然后重试等等...
因此,如果我在"新"的过程中,我应该不会看到任何伤害。
我是这么做的:
1.用于上传的全局函数:

Future updateResizedProfileUrl2(Map<String, dynamic> args) async {
  /// Updating profile cover and logo images urls as individual process
  /// imageType: logo, cover
  String imageType = args['type'];
  print('got into update function');
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  FirebaseFirestore _fs = FirebaseFirestore.instance;
  FirebaseStorage _fst = FirebaseStorage.instance;
  while (true) {
    Reference fileRef =
        _fst.ref(profileStorageDir).child('${imageType}_600x600.png');
    try {
      print('checking fileref $fileRef');
      final refStr = await fileRef.getDownloadURL();
      print('got url $refStr');
      _fs.collection(settingsCollection).doc('profile').update(
        {'media.$imageType': refStr},
      );
      print('updating media strrefStr');
      return;
    } catch (e) {
      print('waaiting....');
      print(e);
      sleep(const Duration(seconds: 2));
    }
  }
}

1.这里我的主要上传功能

MyClass... {
  Future<void> uploadLogoImage(File image) async {
    Reference ref = _fst.ref(profileStorageDir).child('logo.png');
    await ref.putFile(image);
    Map<String, dynamic> args = {
      'type': 'logo',
    };
    print('sent update logo');
    compute(updateResizedProfileUrl2, args);
  }
}

但这不起作用,错误如下:

ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Binding has not yet been initialized.
E/flutter (23103): The "instance" getter on the ServicesBinding binding mixin is only available once that binding has been initialized.
E/flutter (23103): 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 (23103): In a test, one can call "TestWidgetsFlutterBinding.ensureInitialized()" as the first line in the test's "main()" method to initialize the binding.
E/flutter (23103): 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 (23103): #0      BindingBase.checkInstance.<anonymous closure> (package:flutter/src/foundation/binding.dart:284:9)
E/flutter (23103): #1      BindingBase.checkInstance (package:flutter/src/foundation/binding.dart:366:6)
E/flutter (23103): #2      ServicesBinding.instance (package:flutter/src/services/binding.dart:54:54)
E/flutter (23103): #3      BasicMessageChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:166:45)
E/flutter (23103): #4      BasicMessageChannel.send (package:flutter/src/services/platform_channel.dart:180:38)
E/flutter (23103): #5      FirebaseCoreHostApi.initializeCore (package:firebase_core_platform_interface/src/pigeon/messages.pigeon.dart:201:23)
E/flutter (23103): #6      MethodChannelFirebase._initializeCore (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:29:54)
E/flutter (23103): #7      MethodChannelFirebase.initializeApp (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:73:13)
E/flutter (23103): #8      Firebase.initializeApp (package:firebase_core/src/firebase.dart:43:47)
E/flutter (23103): #9      updateResizedProfileUrl2 (package:appointments/providers/settings_mgr.dart:33:18)
E/flutter (23103): #10     _IsolateConfiguration.applyAndTime.<anonymous closure> (package:flutter/src/foundation/_isolates_io.dart:108:21)
E/flutter (23103): #11     Timeline.timeSync (dart:developer/timeline.dart:160:22)
E/flutter (23103): #12     _IsolateConfiguration.applyAndTime (package:flutter/src/foundation/_isolates_io.dart:106:21)
E/flutter (23103): #13     _spawn (package:flutter/src/foundation/_isolates_io.dart:127:67)
E/flutter (23103): #14     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:17)
E/flutter (23103): #15     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
E/flutter (23103):

我已经初始化了firebase,因为我需要它,我知道隔离有不同的内存,主要...
在全局函数中写入:"WidgetsFlutterBinding. ensureInitialized()"无法正常工作...
我怎样才能达到上述目标?或者我怎样解决它?
谢谢!

7gyucuyw

7gyucuyw1#

简短地说,当firebase存储插件依赖于本地代码时,你不能从isolate运行本地代码。
你需要的是用https://pub.dev/packages/isolate_handlerhttps://pub.dev/packages/flutter_isolate产生一个隔离。这些支持插件,但不是所有的插件都可以工作。我可以确认firebase存储与isolate_handler一起工作。
请记住,即使有了这个解决方案,本地代码仍将在主线程上运行,这就是dart的局限性
flutter使用平台通道与本机代码进行通信,而WidgetsBinding.ensureInitialized()正是它使用这些通道所需要的,这就是您收到此错误的原因。
还有一个问题https://github.com/firebase/flutterfire/issues/9790,它阻止firebase存储在隔离区中正常工作,但最近得到了修复

相关问题