为何Flutter代码中会出现‘data2未初始化’错误?
问题:Flutter中late声明的data2触发未初始化错误
我在Flutter代码中尝试从FutureBuilder已初始化的data列表中提取字符串存入data2,但触发了‘data2 has not been initialized’错误。data与data2均使用late关键字声明,data可正常工作,但data2不行,请问原因是什么?
变量声明代码:
late List<Album> data; late List<String> data2;
完整代码:
import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; const List<String> list = <String>['One', 'Two', 'Three', 'Four']; Future<List<Album>> fetchAlbum() async { final response = await http.get( Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db')); print(response); Map<String, dynamic> userMap = jsonDecode(response.body); if (response.statusCode == 200) { return (userMap['employees'] as List) .map((e) => Album.fromJson(e)) .toList(); } else { throw Exception('Failed to load album'); } } class Album { final int userId; final int id; final String title; Album(this.userId, this.id, this.title); Album.fromJson(Map<String, dynamic> json) : userId = json['userId'], id = json['id'], title = json['title']; Map<String, dynamic> toJson() => { 'userId': userId, 'id': id, 'title': title, }; } void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { late Future<Album> futureAlbum; late Future<List<Album>> user; late List<Album> data; late List<String> data2; @override void initState() { super.initState(); user = fetchAlbum(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( brightness: Brightness.dark, primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('Fetch Data Example'), ), body: Column(children: <Widget>[ Expanded( child: const DropdownButtonExample(), ), Expanded( child: FutureBuilder<List<Album>>( future: user, builder: (context, snapshot) { if (snapshot.hasData) { data = snapshot.data ?? []; print('${data[4].title}'); return ListView.builder( itemBuilder: (context, index) { data2[index] = data[index].title; return Column(children: [ Text(data[index].title ?? ""), ]); }, itemCount: data.length, ); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return Center( child: const CircularProgressIndicator(), ); }, ), ) ]), ), ); } } class DropdownButtonApp extends StatelessWidget { const DropdownButtonApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('DropdownButton Sample')), body: const Center( child: DropdownButtonExample(), ), ), ); } } class DropdownButtonExample extends StatefulWidget { const DropdownButtonExample({super.key}); @override State<DropdownButtonExample> createState() => _DropdownButtonExampleState(); } class _DropdownButtonExampleState extends State<DropdownButtonExample> { String dropdownValue = list.first; @override Widget build(BuildContext context) { return DropdownButton<String>( value: dropdownValue, icon: const Icon(Icons.arrow_downward), elevation: 16, style: const TextStyle(color: Colors.deepPurple), underline: Container( height: 2, color: Colors.deepPurpleAccent, ), onChanged: (String? value) { setState(() { dropdownValue = value!; }); }, items: list.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }).toList(), ); } }
原因分析
- data已完成初始化:在
snapshot.hasData分支中,你通过data = snapshot.data ?? []直接给data赋值了一个具体的List实例,满足了late关键字要求的“在使用前完成初始化”的条件。 - data2未被初始化:你仅声明了
late List<String> data2,但从未给它分配实际的List对象。代码中直接使用data2[index] = data[index].title试图赋值时,data2还是一个空引用,没有对应的List容器来存储元素,因此触发未初始化错误。
修复方案
方式一:提前初始化固定长度的List
在给元素赋值前,先创建一个和data长度一致的List:
if (snapshot.hasData) { data = snapshot.data ?? []; // 初始化data2为对应长度的List data2 = List<String>.filled(data.length, ''); print('${data[4].title}'); return ListView.builder( itemBuilder: (context, index) { data2[index] = data[index].title; return Column(children: [ Text(data[index].title ?? ""), ]); }, itemCount: data.length, ); }
方式二:初始化空List后逐个添加元素
如果不需要固定长度,可以先创建空List,再通过add方法填充:
if (snapshot.hasData) { data = snapshot.data ?? []; // 初始化空List data2 = []; print('${data[4].title}'); return ListView.builder( itemBuilder: (context, index) { data2.add(data[index].title); return Column(children: [ Text(data[index].title ?? ""), ]); }, itemCount: data.length, ); }
方式三:直接通过map转换生成(更简洁)
无需在ListView.builder中逐个赋值,直接通过map方法一次性生成data2:
if (snapshot.hasData) { data = snapshot.data ?? []; // 直接转换生成data2 data2 = data.map((album) => album.title).toList(); return ListView.builder( itemBuilder: (context, index) { return Column(children: [ Text(data[index].title ?? ""), ]); }, itemCount: data.length, ); }
内容的提问来源于stack exchange,提问作者crag hack
相关产品推荐
相关产品推荐

