【问题标题】:flutter run firebase storage and firestore in new process or isolate causes binding issueflutter 在新进程中运行 firebase 存储和 firestore 或隔离导致绑定问题
【发布时间】:2022-12-30 06:03:04
【问题描述】:

我正在构建一个用户上传徽标的应用程序,我已经在 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,因为我需要它,而且我知道 isolate 与 main 具有不同的内存......

    写作:全局函数中的“WidgetsFlutterBinding.ensureInitialized()”也不起作用......

    我怎样才能实现上述目标?或者我如何解决它?

    谢谢!!

【问题讨论】:

  • 看看这个 stackoverflow link1 & link2 和这个 github 中的建议
  • 谢谢,但没有人帮助

标签: flutter firebase google-cloud-firestore firebase-storage


【解决方案1】:

简而言之,您不能从以标准方式生成的 isolate 运行本机代码,而 firebase 存储插件依赖于本机代码。

您需要的是使用 https://pub.dev/packages/isolate_handlerhttps://pub.dev/packages/flutter_isolate 生成隔离。那些支持插件,但并非所有插件都可以工作。我可以确认 firebase 存储与 isolate_handler 一起工作

flutter 使用平台通道与本机代码进行通信,而 WidgetsBinding.ensureInitialized() 是使用这些通道所需要的,这就是您收到此错误的原因。

还有一个问题 https://github.com/firebase/flutterfire/issues/9790 阻止了 firebase 存储在隔离中正常工作,但最近得到修复

【讨论】:

    猜你喜欢
    • 2018-04-23
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2011-05-06
    • 2020-09-06
    相关资源
    最近更新 更多