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

Flutter调用API报错:type 'Null' is not a subtype of type 'List<dynamic>'

API调用报错:type 'Null' is not a subtype of type 'List'

Error : type 'Null' is not a subtype of type 'List'

使用同一MovieModel请求其他类型API URL时可正常运行,但请求cast类型API时触发该错误,更换新模型则可正常工作。以下是相关代码:

调用代码

FutureBuilder(
  future: movieObj.fetchMovies(movieType.cast,id: movieData.id),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      List<MovieModel>movieData = snapshot.data??[];
      return layouts(movieData: movieData);
    }
    return Center(child: CircularProgressIndicator(),);
  },
)

MovieModel 代码

// To parse this JSON data, do
//
// final MovieModel = MovieModelFromJson(jsonString);

import 'dart:convert';

MovieModel MovieModelFromJson(String str) => MovieModel.fromJson(json.decode(str));

String MovieModelToJson(MovieModel data) => json.encode(data.toJson());

class MovieModel {
    bool? adult;
    String backdropPath;
    int? id;
    String? originalLanguage;
    String? originalTitle;
    String? overview;
    double? popularity;
    String posterPath;
    String? releaseDate;
    String title;
    bool? video;
    double? voteAverage;
    int? voteCount;

    MovieModel({
        required this.adult,
        required this.backdropPath,
        required this.id,
        required this.originalLanguage,
        required this.originalTitle,
        required this.overview,
        required this.popularity,
        required this.posterPath,
        required this.releaseDate,
        required this.title,
        required this.video,
        required this.voteAverage,
        required this.voteCount,
    });

    factory MovieModel.fromJson(Map<String, dynamic> json) => MovieModel(
        adult: json["adult"],
        backdropPath: json["backdrop_path"],
  
        id: json["id"],
        originalLanguage: json["original_language"],
        originalTitle: json["original_title"],
        overview: json["overview"],
        popularity: json["popularity"]?.toDouble(),
        posterPath: json["poster_path"],
        releaseDate: json["release_date"],
        title: json["title"],
        video: json["video"],
        voteAverage: json["vote_average"]?.toDouble(),
        voteCount: json["vote_count"],
    );

    Map<String, dynamic> toJson() => {
        "adult": adult,
        "backdrop_path": backdropPath,
        "id": id,
        "original_language": originalLanguage,
        "original_title": originalTitle,
        "overview": overview,
        "popularity": popularity,
        "poster_path": posterPath,
        "release_date": releaseDate,
        "title": title,
        "video": video,
        "vote_average": voteAverage,
        "vote_count": voteCount,
    };
}

请求类代码

import 'dart:convert';
import 'package:http/http.dart';
import 'package:movie_application/api%20Integration/model/movieModel.dart';
import 'package:movie_application/api%20Integration/model/similarModel.dart';
import 'package:movie_application/constants/apiConstants.dart';

enum movieType {
  nowPlaying,
  popular,
  topRated,
  upComing,
  similar,
  latest,
  videos,
  cast
}

class movieClass {
  Future<List<MovieModel>?> fetchMovies(movieType type, {id}) async {
    var url = '';
    if (type == movieType.nowPlaying) {
      url = movieUrl + CnowPlaying;
    } else if (type == movieType.popular) {
      url = movieUrl + Cpopular;
    } else if (type == movieType.topRated) {
      url = movieUrl + CtopRated;
    } else if (type == movieType.upComing) {
      url = movieUrl + CupComing;
    } else if (type == movieType.cast) {
      url = movieUrl + id.toString() + Ccast;
    } else if (type == movieType.similar) {
      url = movieUrl + id.toString() + Csimilar;
    } else if (type == movieType.videos) {
      url = movieUrl + id.toString() + Cvideos;
    }
    Response response = await get(Uri.parse(url + '?api_key=3c63914fd23ecbed6507f4396ed68164'));
    Map<String,dynamic>jsonBody = jsonDecode(response.body);
    List<dynamic>result = jsonBody['results'];
    List<MovieModel>resultList = result.map((e) => MovieModel.fromJson(e)).toList();
    print(url);
    return resultList;
  }

}

问题原因与解决方案

核心原因

  1. API返回结构不匹配:Cast接口的返回数据中,演员列表的字段不是results(比如常见的电影演员接口返回结构是{"id":xxx, "cast": [...], "crew": [...]}),直接取jsonBody['results']会得到null,赋值给List<dynamic>就会触发类型转换错误。
  2. 模型字段不匹配:演员数据的字段(如name、character)和MovieModel的电影字段(如title、release_date)完全不对应,强行用MovieModel解析会导致字段缺失或类型错误。

解决方案

步骤1:创建演员专属模型

import 'dart:convert';

CastModel CastModelFromJson(String str) => CastModel.fromJson(json.decode(str));

String CastModelToJson(CastModel data) => json.encode(data.toJson());

class CastModel {
    bool? adult;
    int? id;
    String? name;
    String? character;
    String? profilePath;
    // 根据实际API返回字段补充其他属性

    CastModel({
        this.adult,
        this.id,
        this.name,
        this.character,
        this.profilePath,
    });

    factory CastModel.fromJson(Map<String, dynamic> json) => CastModel(
        adult: json["adult"],
        id: json["id"],
        name: json["name"],
        character: json["character"],
        profilePath: json["profile_path"],
    );

    Map<String, dynamic> toJson() => {
        "adult": adult,
        "id": id,
        "name": name,
        "character": character,
        "profile_path": profilePath,
    };
}

步骤2:修改请求方法适配Cast接口

在movieClass中新增演员列表请求方法,或修改原方法区分处理:

// 新增获取演员列表的独立方法
Future<List<CastModel>?> fetchCast(int movieId) async {
  final url = movieUrl + movieId.toString() + Ccast;
  final response = await get(Uri.parse(url + '?api_key=3c63914fd23ecbed6507f4396ed68164'));
  final jsonBody = jsonDecode(response.body);
  // 取cast字段而非results,同时添加空值兜底
  final List<dynamic> castList = jsonBody['cast'] ?? [];
  return castList.map((e) => CastModel.fromJson(e)).toList();
}

步骤3:更新FutureBuilder调用

FutureBuilder(
  future: movieObj.fetchCast(movieData.id),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      List<CastModel>castData = snapshot.data??[];
      return castLayouts(movieData: castData); // 替换为演员专属布局组件
    }
    return Center(child: CircularProgressIndicator(),);
  },
)

额外优化建议

  • 所有字段访问都添加空值判断(如jsonBody['results'] ?? []),避免null直接赋值给List类型。
  • 不同类型的API返回对应不同的数据模型,不要强行复用不匹配的模型,保证数据解析的准确性。

内容的提问来源于stack exchange,提问作者Mr. Anonymous

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:15:09