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; } }
问题原因与解决方案
核心原因
- API返回结构不匹配:Cast接口的返回数据中,演员列表的字段不是
results(比如常见的电影演员接口返回结构是{"id":xxx, "cast": [...], "crew": [...]}),直接取jsonBody['results']会得到null,赋值给List<dynamic>就会触发类型转换错误。 - 模型字段不匹配:演员数据的字段(如
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
相关产品推荐
相关产品推荐

