You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:09:21