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

Flutter中调用null对象的data getter引发No Such Method Error求助

解决Flutter/Dart中No Such Method Error(The getter data was called on null)的问题

核心问题分析

错误源于对JSON数据结构的访问逻辑错误,以及FutureBuilder使用不当,导致尝试在null对象上调用data getter。下面是具体修复步骤:


步骤1:修复API调用中的冗余代码

response.statusCode是同步属性,无需加await,直接判断即可:

Future<Map<String, dynamic>> fetchBuildNews() async {
    final prefs = await SharedPreferences.getInstance();
    accessToken = prefs.getString('access_Token') ?? '';
    final Map<String, String> headers = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $accessToken',
    };
    final response = await http.get(Uri.parse('https://idonor.ae/api/latest-news'),
        headers: headers);
    // 移除多余的await
    if (response.statusCode == 200) {
      final items = Map<String, dynamic>.from(json.decode(response.body));
      return items;
    } else {
      throw Exception('Failed to load data');
    }
}

步骤2:修正FutureBuilder的数据访问逻辑

JSON根对象是包含success、data、message的Map,data下的news才是新闻数组。之前错误地将根Map当作数组处理,导致索引访问错误。修改buildNews方法:

Widget buildNews() => Container(
    width: 300,
    height: 185,
    child: FutureBuilder<Map<String, dynamic>>(
      future: fetchBuildNews(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          // 正确获取新闻数组
          final List<dynamic> newsList = snapshot.data!['data']['news'];
          return ListView.builder(
            shrinkWrap: true,
            scrollDirection: Axis.horizontal,
            itemCount: newsList.length, // 用新闻数组长度作为itemCount
            itemBuilder: (context, index) {
              final newsItem = newsList[index];
              return Container(
                  width: 300,
                  height: 185,
                  child: Container(
                    height: 185.0,
                    width: MediaQuery.of(context).size.width - 100.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(5),
                        color: Colors.blue,
                        image: DecorationImage(
                            image: NetworkImage(
                                newsItem['news_image'] ?? '' // 匹配JSON中的下划线key
                            ),
                            fit: BoxFit.cover)),
                    child: Center(
                      child: Text(
                        newsItem['title'] ?? 'No Title',
                        style: TextStyle(
                            fontFamily: 'Poppins, SemiBold', 
                            color: '#336699'.hexToColor(), 
                            fontSize: 18, 
                            fontWeight: FontWeight.w700),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ));
            },
          );
        } else if (snapshot.hasError) {
          print('${snapshot.error}');
          return Text('${snapshot.error}');
        }
        return CircularProgressIndicator();
      },
    ),
);

步骤3:优化FutureBuilder避免重复请求

直接在FutureBuilder的future参数中调用API会导致每次组件重建都发起请求,建议将future实例存入State变量:

// 在State类中定义变量
late Future<Map<String, dynamic>> _newsFuture;

@override
void initState() {
  super.initState();
  // 仅在初始化时调用一次API
  _newsFuture = fetchBuildNews();
}

// 后续在buildNews中使用_newsFuture
Widget buildNews() => Container(
    width: 300,
    height: 185,
    child: FutureBuilder<Map<String, dynamic>>(
      future: _newsFuture,
      // 其余代码保持不变
    ),
);

可选:使用模型类提升数据安全性

为避免手动解析Map时的key拼写错误和空指针问题,推荐用json_serializable生成模型类:

  1. 添加依赖到pubspec.yaml:
dependencies:
  json_annotation: ^4.8.1

dev_dependencies:
  build_runner: ^2.4.4
  json_serializable: ^6.7.0
  1. 创建模型类:
import 'package:json_annotation/json_annotation.dart';

part 'news_response.g.dart';

@JsonSerializable()
class NewsResponse {
  final bool success;
  final NewsData data;
  final String message;

  NewsResponse({required this.success, required this.data, required this.message});

  factory NewsResponse.fromJson(Map<String, dynamic> json) => _$NewsResponseFromJson(json);
  Map<String, dynamic> toJson() => _$NewsResponseToJson(this);
}

@JsonSerializable()
class NewsData {
  final List<NewsItem> news;

  NewsData({required this.news});

  factory NewsData.fromJson(Map<String, dynamic> json) => _$NewsDataFromJson(json);
  Map<String, dynamic> toJson() => _$NewsDataToJson(this);
}

@JsonSerializable()
class NewsItem {
  final int id;
  @JsonKey(name: 'user_id')
  final int userId;
  final String title;
  final String content;
  @JsonKey(name: 'published_at')
  final String publishedAt;
  @JsonKey(name: 'created_at')
  final String createdAt;
  @JsonKey(name: 'updated_at')
  final String updatedAt;
  @JsonKey(name: 'news_image')
  final String newsImage;

  NewsItem({
    required this.id,
    required this.userId,
    required this.title,
    required this.content,
    required this.publishedAt,
    required this.createdAt,
    required this.updatedAt,
    required this.newsImage,
  });

  factory NewsItem.fromJson(Map<String, dynamic> json) => _$NewsItemFromJson(json);
  Map<String, dynamic> toJson() => _$NewsItemToJson(this);
}
  1. 运行生成命令:
flutter pub run build_runner build
  1. 修改API调用返回模型类:
Future<NewsResponse> fetchBuildNews() async {
    final prefs = await SharedPreferences.getInstance();
    accessToken = prefs.getString('access_Token') ?? '';
    final Map<String, String> headers = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $accessToken',
    };
    final response = await http.get(Uri.parse('https://idonor.ae/api/latest-news'),
        headers: headers);
    if (response.statusCode == 200) {
      return NewsResponse.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load data');
    }
}
  1. 更新FutureBuilder逻辑:
Widget buildNews() => Container(
    width: 300,
    height: 185,
    child: FutureBuilder<NewsResponse>(
      future: _newsFuture,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final newsList = snapshot.data!.data.news;
          return ListView.builder(
            shrinkWrap: true,
            scrollDirection: Axis.horizontal,
            itemCount: newsList.length,
            itemBuilder: (context, index) {
              final newsItem = newsList[index];
              return Container(
                  width: 300,
                  height: 185,
                  child: Container(
                    height: 185.0,
                    width: MediaQuery.of(context).size.width - 100.0,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(5),
                        color: Colors.blue,
                        image: DecorationImage(
                            image: NetworkImage(newsItem.newsImage),
                            fit: BoxFit.cover)),
                    child: Center(
                      child: Text(
                        newsItem.title,
                        style: TextStyle(
                            fontFamily: 'Poppins, SemiBold', 
                            color: '#336699'.hexToColor(), 
                            fontSize: 18, 
                            fontWeight: FontWeight.w700),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ));
            },
          );
        } else if (snapshot.hasError) {
          print('${snapshot.error}');
          return Text('${snapshot.error}');
        }
        return CircularProgressIndicator();
      },
    ),
);

内容的提问来源于stack exchange,提问作者AzeTech

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:40:04