【问题标题】:Error while attempting to create a stream to listen to changes in Firebase database (flutter)尝试创建流以侦听 Firebase 数据库中的更改时出错(颤振)
【发布时间】:2020-11-30 17:54:59
【问题描述】:

我正在将图片上传到 Firebase 存储,然后将链接保存到 Firebase 数据库中。 我创建了一个流来监听数据库中的变化,所以每次上传新图像时,它都会显示在应用程序中。

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

Flutter 医生: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,0,720,1560) new=(0,0,720,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,0-720,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,0-720,1560} of ViewRootImpl@c270626[MainActivity]
D/ViewRootImpl@c270626[MainActivity]( 8984): Relayout returned: old=(0,0,720,1560) new=(0,0,720,1560) req=(720,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,0-720,1560}
D/mali_winsys( 8984): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
D/SurfaceView( 8984): surfaceChanged (720,1560) 1 #8 io.flutter.embedding.android.FlutterSurfaceView{99c7814 V.E...... ........ 0,0-720,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(),
      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(() {
              pictureNumber++;
              pictures.add(Image.network('$link'));
              print(link);
              _firestore.collection('links').orderBy('index');
            });
            print(pictures.length);
//            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').orderBy('link').snapshots(),
      // ignore: missing_return
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Color(0xFF3E3E3E),
            ),
          );
        }
        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,
          child: Column(
            children: [
              Expanded(
                  child: ListView.builder(
                itemCount: pictures.length,
                itemBuilder: (context, index) => Padding(
                  padding: EdgeInsets.all(16.0),
                  child: pictures[index],
                ),
              )),
            ],
          ),
        );
      },
    );
  }
}

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

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

【问题讨论】:

    标签: android firebase android-studio flutter google-cloud-firestore


    【解决方案1】:

    该错误的简单含义是您将QuerySnapshot 对象视为List

    【讨论】:

    • 那么如何将 QuerySnapshot 用于我正在寻找的功能?
    【解决方案2】:

    我认为错误就在这里

    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。这会将DocumentSnapshotList 传递给links。您想迭代文档而不是 QuerySnapshot 本身。记住snapshot 的类型是AsyncSnapshot&lt;QuerySnapshot&gt;,所以snapshot.data 将返回QuerySnapshot。然后.documents getter 将返回一个List&lt;DocumentSnapshot&gt;,这是查询的结果。

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

    【讨论】:

    • 我编辑了问题,因为有一个新问题。如果你也能和我一起,我会非常高兴。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2020-07-02
    • 2020-02-20
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    相关资源
    最近更新 更多