Flutter应用崩溃:type 'Null' is not a subtype of type 'String' 问题求助
解决Flutter应用崩溃:
type 'Null' is not a subtype of type 'String' 错误信息
/flutter ( 5006): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'Null' is not a subtype of type 'String' E/flutter ( 5006): #0 Video.fromSnap package:tiktok_project/models/video.dart:48 E/flutter ( 5006): #1 VideoController.onInit.<anonymous closure> package:tiktok_project/controllers/video_controller.dart:19
问题原因
你的Video类中所有String类型属性都被声明为非空(没有?修饰),但从Firestore读取数据时,某个字段的值为null,导致在fromSnap方法中将null赋值给非空String时触发类型转换错误。
解决方案
方案1:修复Firestore数据完整性
检查Firestore中videos集合的所有文档,确认以下字段不存在null值或缺失:
- username
- uid
- id
- songName
- caption
- videoUrl
- thumbnail
- profilePhoto
补充所有缺失或为null的字段值后,崩溃即可解决。
方案2:修改Video类支持可选字段(推荐)
如果无法保证Firestore数据绝对完整,修改Video类属性为可空类型,并在构造时提供默认值,避免崩溃:
import 'package:cloud_firestore/cloud_firestore.dart'; class Video { String? username; String? uid; String? id; List? likes; int? commentCount; int? shareCount; String? songName; String? caption; String? videoUrl; String? thumbnail; String? profilePhoto; Video({ this.username, this.uid, this.id, this.likes, this.commentCount, this.shareCount, this.songName, this.caption, this.videoUrl, this.profilePhoto, this.thumbnail, }); Map<String, dynamic> toJson() => { "username": username, "uid": uid, "profilePhoto": profilePhoto, "id": id, "likes": likes, "commentCount": commentCount, "shareCount": shareCount, "songName": songName, "caption": caption, "videoUrl": videoUrl, "thumbnail": thumbnail, }; static Video fromSnap(DocumentSnapshot snap) { var snapshot = snap.data() as Map<String, dynamic>; return Video( username: snapshot['username'] ?? '', uid: snapshot['uid'] ?? '', id: snapshot['id'] ?? '', likes: snapshot['likes'] ?? [], commentCount: snapshot['commentCount'] ?? 0, shareCount: snapshot['shareCount'] ?? 0, songName: snapshot['songName'] ?? '', caption: snapshot['caption'] ?? '', videoUrl: snapshot['videoUrl'] ?? '', profilePhoto: snapshot['profilePhoto'] ?? '', thumbnail: snapshot['thumbnail'] ?? '', ); } }
通过??运算符为可能为null的字段设置默认值(空字符串、空数组、0),确保即使Firestore返回null,也不会触发类型错误。
方案3:添加空值检查(精准定位问题)
在fromSnap方法中提前检查字段是否存在且非null,提前抛出明确错误:
static Video fromSnap(DocumentSnapshot snap) { var snapshot = snap.data() as Map<String, dynamic>; // 检查关键必填字段 if (snapshot['username'] == null) throw ArgumentError('文档缺失username字段'); if (snapshot['uid'] == null) throw ArgumentError('文档缺失uid字段'); // 其他必填字段同理添加检查 return Video( username: snapshot['username'], uid: snapshot['uid'], id: snapshot['id'], likes: snapshot['likes'], commentCount: snapshot['commentCount'], shareCount: snapshot['shareCount'], songName: snapshot['songName'], caption: snapshot['caption'], videoUrl: snapshot['videoUrl'], profilePhoto: snapshot['profilePhoto'], thumbnail: snapshot['thumbnail'], ); }
这种方式能快速定位到问题文档,但需要确保所有数据都符合必填要求。
额外修复:likeVideo方法逻辑问题
你的likeVideo方法存在逻辑错误,无论是否已点赞都会执行最后的点赞操作,修复如下:
likeVideo(String id) async { DocumentSnapshot doc = await firestore.collection('videos').doc(id).get(); var uid = authController.user.uid; List likes = (doc.data() as dynamic)['likes'] ?? []; if (likes.contains(uid)) { await firestore.collection('videos').doc(id).update({ 'likes': FieldValue.arrayRemove([uid]) }); } else { await firestore.collection('videos').doc(id).update({ 'likes': FieldValue.arrayUnion([uid]) }); } }
内容的提问来源于stack exchange,提问作者Harun Begic
相关产品推荐
相关产品推荐

