尝试创建流以侦听Firebase数据库中的更改时出错颤振

问题描述

我将图片上传到Firebase存储,然后将链接保存到Firebase数据库中。 我创建了一个流来侦听数据库中的更改,因此每次上传新图像时,该图像都会显示在应用程序中。

但是,每次我运行该应用程序时,都会出现错误,并且该应用程序崩溃。 (如此处所示:https://prnt.sc/txj3jc)。

扑打医生:https://prnt.sc/txj5q8

代码

import 'package:Flutter/material.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:Flutter/widgets.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

final _firestore = Firestore.instance;
int pictureNumber = 0;
List<Widget> pictures = [];

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),home: MyHomePage(),);
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _scaffoldKey = GlobalKey<ScaffoldState>();
  String imageLink;
  File _image;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.blue,child: Icon(
          Icons.add,size: 30,),onpressed: () async {
          _image =
              // ignore: deprecated_member_use
              await ImagePicker.pickImage(source: ImageSource.gallery);

          FirebaseStorage firebaseStorage = FirebaseStorage.instance;
          StorageReference rootReference = firebaseStorage.ref();
          StorageReference pictureFolderRef =
              rootReference.child('pictures').child('$pictureNumber');
          pictureFolderRef.putFile(_image).onComplete.then((storageTask) async {
            String link = await storageTask.ref.getDownloadURL();
            await _firestore
                .collection('links')
                .add({'link': link,'index': pictureNumber});
            setState(() {
              pictures.add(Image.network('$link'));
              print(link);
              _firestore.collection('links').orderBy('index');
            });
            pictureNumber++;
//            setState(() {
//              imageLink = link;
//              pictures.add(
//                Image.network('$imageLink'),//              );
//              print(pictures.length);
//            });
          });
        },//      body: Container(
//        width: double.infinity,//        child: Column(
//          children: [
//            Expanded(
//                child: ListView.builder(
//              itemCount: pictures.length,//              itemBuilder: (context,index) => Padding(
//                padding: EdgeInsets.all(16.0),//                child: pictures[index],//              ),//            )),//          ],//        ),//      ),key: _scaffoldKey,body: PictureStream(),);
  }
}

class PictureStream extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: _firestore.collection('links').snapshots(),// ignore: missing_return
      builder: (context,snapshot) {
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Color(0xFF3E3E3E),);
        }
        final links = snapshot.data;
        for (var linkData in links) {
          final index = linkData.data['index'];
          final link = linkData.data['link'];

          pictures.add(Image.network(link));
        }
        return Container(
          width: double.infinity,child: Column(
            children: [
              Expanded(
                  child: ListView.builder(
                itemCount: pictures.length,itemBuilder: (context,index) => Padding(
                  padding: EdgeInsets.all(16.0),child: pictures[index],)),],);
      },);
  }
}

错误

Performing hot restart...
Syncing files to device SM A205F...
Restarted application in 3,046ms.
D/SurfaceView( 8984): onWindowVisibilityChanged(4) false io.Flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,0-720,1560} of ViewRootImpl@c270626[MainActivity]
D/ViewRootImpl@c270626[MainActivity]( 8984): Relayout returned: old=(0,720,1560) new=(0,1560) req=(720,1560)4 dur=11 res=0x1 s={false 0} ch=false
D/ViewRootImpl@c270626[MainActivity]( 8984): stopped(false) old=true
D/SurfaceView( 8984): windowStopped(false) false io.Flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,1560} of ViewRootImpl@c270626[MainActivity]
D/ViewRootImpl@c270626[MainActivity]( 8984): stopped(false) old=false
D/SurfaceView( 8984): onWindowVisibilityChanged(0) true io.Flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,1560)0 dur=15 res=0x7 s={true 515117469696} ch=true
D/Openglrenderer( 8984): createReliableSurface : 0x77f381c840,0x77ef64d000
D/mali_winsys( 8984): EGLint new_window_surface(egl_winsys_display *,void *,EGLSurface,EGLConfig,egl_winsys_surface **,EGLBoolean) returns 0x3000
D/SurfaceView( 8984): surfaceCreated 1 #8 io.Flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,1560}
D/mali_winsys( 8984): EGLint new_window_surface(egl_winsys_display *,EGLBoolean) returns 0x3000
D/SurfaceView( 8984): surfaceChanged (720,1560) 1 #8 io.Flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,1560}
D/ViewRootImpl@c270626[MainActivity]( 8984): MSG_WINDOW_FOCUS_CHANGED 1 1
D/InputMethodManager( 8984): prepareNavigationBarInfo() DecorView@2fcf57c[MainActivity]
D/InputMethodManager( 8984): getNavigationBarColor() -855310
D/InputMethodManager( 8984): prepareNavigationBarInfo() DecorView@2fcf57c[MainActivity]
D/InputMethodManager( 8984): getNavigationBarColor() -855310
V/InputMethodManager( 8984): Starting input: tba=menachemmaron14082004.image_firebase ic=null mNaviBarColor -855310 mIsGetNaviBarColorSuccess true,NavVisible : true,NavTrans : false
D/InputMethodManager( 8984): startInputInner - Id : 0
I/InputMethodManager( 8984): startInputInner - mService.startInputOrWindowGainedFocus
I/Flutter ( 8984): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/Flutter ( 8984): The following _TypeError was thrown building StreamBuilder<QuerySnapshot>(dirty,state:
I/Flutter ( 8984): _StreamBuilderBaseState<QuerySnapshot,AsyncSnapshot<QuerySnapshot>>#3e08b):
I/Flutter ( 8984): type 'QuerySnapshot' is not a subtype of type 'Iterable<dynamic>'
I/Flutter ( 8984): 
I/Flutter ( 8984): The relevant error-causing widget was:
I/Flutter ( 8984):   StreamBuilder<QuerySnapshot>
I/Flutter ( 8984):   file:///C:/Users/menac/AndroidStudioProjects/image_firebase/lib/main.dart:99:12
I/Flutter ( 8984): 
I/Flutter ( 8984): When the exception was thrown,this was the stack:
I/Flutter ( 8984): #0      PictureStream.build.<anonymous closure> (package:image_firebase/main.dart:111:30)
I/Flutter ( 8984): #1      StreamBuilder.build (package:Flutter/src/widgets/async.dart:509:81)
I/Flutter ( 8984): #2      _StreamBuilderBaseState.build (package:Flutter/src/widgets/async.dart:127:48)
I/Flutter ( 8984): #3      StatefulElement.build (package:Flutter/src/widgets/framework.dart:4623:28)
I/Flutter ( 8984): #4      ComponentElement.performRebuild (package:Flutter/src/widgets/framework.dart:4506:15)
I/Flutter ( 8984): #5      StatefulElement.performRebuild (package:Flutter/src/widgets/framework.dart:4679:11)
I/Flutter ( 8984): #6      Element.rebuild (package:Flutter/src/widgets/framework.dart:4222:5)
I/Flutter ( 8984): #7      BuildOwner.buildScope (package:Flutter/src/widgets/framework.dart:2627:33)
I/Flutter ( 8984): #8      WidgetsBinding.drawFrame (package:Flutter/src/widgets/binding.dart:864:20)
I/Flutter ( 8984): #9      RendererBinding._handlePersistentFrameCallback (package:Flutter/src/rendering/binding.dart:284:5)
I/Flutter ( 8984): #10     SchedulerBinding._invokeFrameCallback (package:Flutter/src/scheduler/binding.dart:1074:15)
I/Flutter ( 8984): #11     SchedulerBinding.handleDrawFrame (package:Flutter/src/scheduler/binding.dart:1013:9)
I/Flutter ( 8984): #12     SchedulerBinding._handleDrawFrame (package:Flutter/src/scheduler/binding.dart:929:5)
I/Flutter ( 8984): #16     _invoke (dart:ui/hooks.dart:277:10)
I/Flutter ( 8984): #17     _drawFrame (dart:ui/hooks.dart:235:3)
I/Flutter ( 8984): (elided 3 frames from dart:async)
I/Flutter ( 8984): 
I/Flutter ( 8984): ════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following _TypeError was thrown building StreamBuilder<QuerySnapshot>(dirty,state: _StreamBuilderBaseState<QuerySnapshot,AsyncSnapshot<QuerySnapshot>>#3e08b):
type 'QuerySnapshot' is not a subtype of type 'Iterable<dynamic>'

The relevant error-causing widget was: 
  StreamBuilder<QuerySnapshot> file:///C:/Users/menac/AndroidStudioProjects/image_firebase/lib/main.dart:99:12
When the exception was thrown,this was the stack: 
#0      PictureStream.build.<anonymous closure> (package:image_firebase/main.dart:111:30)
#1      StreamBuilder.build (package:Flutter/src/widgets/async.dart:509:81)
#2      _StreamBuilderBaseState.build (package:Flutter/src/widgets/async.dart:127:48)
#3      StatefulElement.build (package:Flutter/src/widgets/framework.dart:4623:28)
#4      ComponentElement.performRebuild (package:Flutter/src/widgets/framework.dart:4506:15)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
type 'QuerySnapshot' is not a subtype of type 'Iterable<dynamic>'
The relevant error-causing widget was: 
  StreamBuilder<QuerySnapshot> file:///C:/Users/menac/AndroidStudioProjects/image_firebase/lib/main.dart:99:12
════════════════════════════════════════════════════════════════════════════════════════════════════

我是Flutter的新手,很抱歉,这是一个愚蠢的错误

编辑: 问题的第一部分已解决,但现在又有一个问题,它会多次显示每个图像,而不是一次。

代码

import 'package:Flutter/material.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:Flutter/widgets.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

final _firestore = Firestore.instance;
int pictureNumber = 0;
List<Widget> pictures = [];

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),'index': pictureNumber});
            setState(() {
              pictureNumber++;
              pictures.add(Image.network('$link'));
              print(link);
              _firestore.collection('links').orderBy('index');
            });
            print(pictures.length);
//            setState(() {
//              imageLink = link;
//              pictures.add(
//                Image.network('$imageLink'),);
  }
}

class PictureStream extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: _firestore.collection('links').orderBy('link').snapshots(),);
        }
        final links = snapshot.data.documents;
        for (var linkData in links) {
          final index = linkData.data['index'];
          final link = linkData.data['link'];
          print(link);
          print(index);

          pictures.add(Image.network(link));
          print(pictures.length);
        }
        return Container(
          width: double.infinity,);
  }
}

Firebase存储-https://prnt.sc/txy8ag Firebase数据库-https://prnt.sc/txya16

它按索引顺序显示所有3张图像-3次,在该应用程序上总共显示9张图像。

解决方法

该错误仅表示您将QuerySnapshot对象视为List

,

我认为错误在这里

final links = snapshot.data;
    for (var linkData in links) {
      final index = linkData.data['index'];
      final link = linkData.data['link'];

      pictures.add(Image.network(link));
    }

您可以转到第111行和第30行进行确认,因为这就是错误所在。您应该执行final links = snapshot.data.documents。这会将List中的DocumentSnapshot传递到links。您要遍历文档而不是QuerySnapshot本身。提醒snapshot 的类型为AsyncSnapshot<QuerySnapshot>,因此snapshot.data将返回QuerySnapshot.documents的获取程序将返回List<DocumentSnapshot>,这是查询的结果。

考虑在编写代码时使用强类型输入,以避免将来出现问题。