Flutter新闻App报错:Null is not a subtype of String求助
问题分析与解决方案
核心异常原因
Null is not a subtype of String 异常是因为你在 Article.fromJson 中用 as String 强制转换可能为null的字段,但Dart中null不属于String类型,当接口返回null时就会触发该异常。而 Source.fromJson 暂时没报错,是因为当前请求的NewsAPI返回的所有文章中source.name字段均不为null,并非该方法没有空值风险。
分步修复代码
1. 修复Article类的Json解析逻辑
将所有可能为null的字段改为可空转换或提供默认值,避免强制类型转换:
import 'package:news_app/source_models.dart'; class Article { Source source; String? author; String? title; String? description; String? url; String? content; // 移除可空字段的required修饰符,匹配字段的可空类型定义 Article({ required this.source, this.author, this.title, this.description, this.url, this.content, }); factory Article.fromJson(Map<String, dynamic> json) { return Article( // 防止source字段为null的极端情况 source: Source.fromJson(json['source'] ?? {}), // 直接转为可空String,或用??转为默认空字符串 author: json['author'] as String?, title: json['title']?.toString() ?? '', description: json['description'] as String? ?? '', url: json['url'] as String? ?? '', content: json['content'] as String? ?? '', ); } Map<String, dynamic> toJson() => <String, dynamic>{ "source": source.toJson(), "author": author, "title": title, "description": description, "url": url, "content": content, }; }
2. 修复Source类的潜在空值风险
给source.name添加默认值,避免未来出现相同异常:
class Source { String name; Source({required this.name}); factory Source.fromJson(Map<String, dynamic> json) { return Source( // 当name为null时用默认值替代 name: json['name'] ?? '未知来源', ); } Map<String, dynamic> toJson() => <String, dynamic>{ "name": name, }; }
3. 修复ApiService的空值断言风险
移除不安全的!空值断言,处理请求失败的情况:
import 'package:news_app/Article.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; class ApiService { static Future<List<Article>> article() async { final http.Response response = await http.get(Uri.parse('https://newsapi.org/v2/everything?domains=wsj.com&apiKey=eac151759e98448f8712913e2028cfd0')); if (response.statusCode == 200) { Map<String, dynamic> json = jsonDecode(response.body); // 防止articles字段为null List<dynamic> body = json['articles'] ?? []; return body.map((item) => Article.fromJson(item)).toList(); } else { // 请求失败时返回空列表或抛出异常,按需选择 return []; // throw Exception('加载文章失败,状态码:${response.statusCode}'); } } }
4. 修复UI的显示逻辑
修正ListView的加载状态判断,移除不安全的空值断言:
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:news_app/ApiService.dart'; import 'package:news_app/Article.dart'; class HomeScreen extends StatefulWidget { @override createState() => _HomeScreen(); } class _HomeScreen extends State<HomeScreen> { bool isWaiting = false; List<Article> articles = []; @override void initState() { super.initState(); IncomingApi(); } void IncomingApi() async { setState(() => isWaiting = true); articles = await ApiService.article(); setState(() => isWaiting = false); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Home'), ), body: isWaiting ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: articles.length, itemBuilder: (context, index) { return NewsContainer(context, articles[index]); }, ), ); } Widget NewsContainer(BuildContext context, Article article) { return Container( child: ListTile( // 处理description为null的情况 title: Text(article.description ?? '无描述'), ), ); } }
内容的提问来源于stack exchange,提问作者Emmanuel Armoo
相关产品推荐
相关产品推荐

