整天尝试自己解决这个问题后,我不得不来寻求帮助。
我正在尝试构建此ListView.builder,它具有固定数量的itemCount。并使用从本地存储的JSON文件检索的数据构建其Widget。
我正在使用Provider传递数据。问题是,在应用启动或热重启时,ListView.builder变成红色并显示错误,然后在四分之一秒后显示我的数据。
我理解为什么会这样,我从json获取的数据列表最初是空的。因此,我将三元运算符设为:provider.data == null ? CircularProgressIndicator() : ListView.builder...
,但这并不能阻止其崩溃。
我不知道为什么,这让我发疯。这是完整的代码:
我们在这里谈论的是一个称为RecommendationCardList的小部件,它通过使用随机数(在列表长度范围内)作为索引来显示上述列表中的小部件。
我在HomeScreen上有一个类似的ListView,名为CategoryCardList,其工作方式与RecommendationCardCardList类似,但是我没有遇到这个问题。另外,主屏幕的其余部分也显示良好,只有RecommendedCardList的部分在短时间内变成红色。
主屏幕课程:
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get user's screen properties
// We are using this properties to adjust size accordingly
// In order to achieve maximum responsivnes for different screen sizes
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
var repoProvider = Provider.of<Repository>(context);
var recipeDataList = repoProvider.recipeDataList;
return Container(
color: backgroundColor,
child: repoProvider.recipeDataList == null
? Center(child: CircularProgressIndicator())
: Padding(
padding: contentPadding,
child: ListView(
children: <Widget>[
AppTitle(),
SizedBox(
height: height * 0.03,
),
Column(
children: <Widget>[
CategoryAndSeeAll(),
CategoryCardsList(height: height, provider: repoProvider),
],
),
SizedBox(
height: height * 0.05,
),
Container(
width: double.infinity,
height: height * 0.1,
decoration: BoxDecoration(
border: Border.all(color: accentColor),
),
child: Text(
'Reserved for AD',
textAlign: TextAlign.center,
),
),
SizedBox(
height: height * 0.05,
),
RecommendedCardsList(height: height, width: width, recipeDataList: recipeDataList),
],
),
),
);
}
}
RecommendedCardsList类:
class RecommendedCardsList extends StatelessWidget {
const RecommendedCardsList({
Key key,
@required this.height,
@required this.width,
@required this.recipeDataList,
}) : super(key: key);
final double height;
final double width;
final recipeDataList;
@override
Widget build(BuildContext context) {
return Container(
height: height * 0.30,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: numberOfRecommendedRecipes,
itemBuilder: (context, counter) {
int randomNumber = Random().nextInt(recipeDataList.length);
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RecommendedCard(
width: width,
height: height,
imagePath: recipeDataList.elementAt(randomNumber).image,
text: recipeDataList.elementAt(randomNumber).title,
),
],
);
}),
);
}
}
存储库类:
class Repository extends ChangeNotifier {
Repository() {
loadJson();
}
var _recipeData;
List<RecipeModel> _recipeDataList = [];
List<RecipeModel> get recipeDataList => _recipeDataList;
void loadJson() async {
var json = await rootBundle.loadString('assets/recipes.json');
var parsedJson = jsonDecode(json);
for (var item in parsedJson) {
_recipeData = RecipeModel.fromJson(item);
_recipeDataList.add(_recipeData);
}
//print('Title:${_recipeDataList[0].title}\nImage:${_recipeDataList[0].image}'); // For debugging
notifyListeners();
}
}
答案 0 :(得分:1)
在build()
小部件的RecommendedCardsList
中将以下条件作为第一行。
if(recipeDataList == null || recipeDataList.length == 0){
return Container();
}
答案 1 :(得分:0)
此错误与以下事实有关:代码在列表中搜索了索引,并且此索引大于列表长度。
我认为错误在于该部分:
int randomNumber = Random().nextInt(recipeDataList.length);
假设长度为10,则随机函数将检索0到10之间的数字,但最后一个索引为9。
考虑到这一点,我有两个建议:
1)
// changing ternary logic
(repoProvider.recipeDataList == null && repoProvider.recipeDataList.length > 0)
2)
// inside ListView.Builder change to get the list length
itemCount: recipeDataList.length