问题描述
我将图片上传到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
════════════════════════════════════════════════════════════════════════════════════════════════════
编辑: 问题的第一部分已解决,但现在又有一个问题,它会多次显示每个图像,而不是一次。
代码:
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>
,这是查询的结果。
考虑在编写代码时使用强类型输入,以避免将来出现问题。