我有两个列表视图构建器,如下图所示:
尝试获取特定项目列表时出错,这是以下错误:
RangeError (index): Invalid value: Valid value range is empty: 4
When the exception was thrown, this was the stack:
#0 List.[] (dart:core-patch/growable_array.dart:254:60)
#1 AppCubit.changeCategoryModelState (package:ipet/shared/cubit/cubit.dart:116:35)
#2 CategoriesScreen.buildPetsCategoryItem.<anonymous closure>.<anonymous closure> (package:ipet/modules/categories/categories_screen.dart:97:43)
#3 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
#4 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:607:11)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#0916b
debugOwner: GestureDetector
state: ready
won arena
finalPosition: Offset(272.1, 219.8)
finalLocalPosition: Offset(51.1, 42.8)
button: 1
sent tap down
所以我想在点击 buildPetsCategoryItem()
中的项目时只需更改 buildCategoriesListView()
那么最好的方法是什么...
这是下面的代码:
return SingleChildScrollView(
controller: cubit.scrollController,
physics: BouncingScrollPhysics(),
child: Column(
children: [
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: CustomText(
text: "Categories",
),
),
SizedBox(
height: 30,
),
// buildCategoryItem(context),
buildPetsCategoryItem(context),
buildCategoriesListView(cubit)
],
),
);
更清楚地说,我在下面的类别构建器中有这个:
Widget buildPetsCategoryItem(context) {
return Container(
height: 120,
child: ListView.builder(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: AppCubit.get(context).petsCategories.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.only(top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
AppCubit.get(context).changePetsCategoryBorder(index);
AppCubit.get(context).changeCategoryModelState(index);
},
child: Container(
width: 60,
height: 60,
margin: EdgeInsets.symmetric(horizontal: 18),
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: customShadow,
border:
AppCubit.get(context).selectedPetsCategory == index
? Border.all(
color: secondaryGreen,
width: 2,
)
: null,
borderRadius: BorderRadius.circular(20),
),
child: Image.network(
AppCubit.get(context).petsCategories[index].image,
scale: 1.8,
),
),
),
SizedBox(
height: 6,
),
Text(
AppCubit.get(context).petsCategories[index].name,
style: TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
);
},
),
);
}
这是 CategoriesListView:
ListView buildCategoriesListView(AppCubit cubit) {
return ListView.builder(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
// scrollDirection: Axis.horizontal,
itemCount: cubit.currentCategoryPets.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
navigateTo(
context,
DetailsScreen(
pets: cubit.currentCategoryPets[index],
),
);
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: PetCard(
petId: cubit.currentCategoryPets[index].id,
petName: cubit.currentCategoryPets[index].name,
age: cubit.currentCategoryPets[index].age,
breed: cubit.currentCategoryPets[index].petType,
gender: cubit.currentCategoryPets[index].gender,
distance: cubit.currentCategoryPets[index].distance,
imagePath: cubit.currentCategoryPets[index].image,
),
),
);
},
);
}
因为我有两种获取每个类别的 PetsModel
数据的方法,一个获取所有宠物,另一个获取 Cats:
List<PetsModel> pets = [];
List<PetsModel> cats = [];
void getPetsData() {
FirebaseFirestore.instance.collection('pets').get().then((value) {
value.docs.forEach((element) {
pets.add(PetsModel.fromJson(element.data()));
});
emit(AppGetPetsSuccessState());
}).catchError((error) {
emit(AppGetPetsErrorState(error.toString()));
});
}
void getCatsData() {
FirebaseFirestore.instance.collection('pets').where('type', isEqualTo: 'cat').get().then((value) {
value.docs.forEach((element) {
cats.add(PetsModel.fromJson(element.data()));
});
emit(AppGetPetsSuccessState());
}).catchError((error) {
emit(AppGetPetsErrorState(error.toString()));
});
}
我尝试创建一种将 Category Model State
更改为以下内容的方法:
PetsModel petModel;
List<PetsModel> currentCategoryModel = [];
void changeCategoryModelState(int position) {
petModel = currentCategoryPets[position];
if (position == 4) getPetsData();
if (position == 5) getCatsData();
emit(AppChangeCategoryModelState());
}
这是包含 BlocProvider 的主类:
return BlocProvider(
create: (BuildContext context) => AppCubit()
..getUserData()
..getCategoriesData()
..getPetsData()
..getCatsData()
..handleScroll(),
child: BlocConsumer<AppCubit, AppStates>(...),);
有关更多信息,这是宠物卡小部件:
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
// final randomColor = colors[_random.nextInt(colors.length)];
return Container(
margin: EdgeInsets.symmetric(horizontal: 20),
height: 240,
child: Stack(
children: [
Container(
// height: 200,
margin: EdgeInsets.only(
top: 70,
bottom: 20,
),
child: Row(
children: [
Container(
width: size.width * 0.48,
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomText(
text: petName,
fontSize: 20,
fontWeight: FontWeight.bold,
maxLine: 1,
overflow: TextOverflow.ellipsis,
),
Icon(
gender == 'female'
? FontAwesomeIcons.venus
: FontAwesomeIcons.mars,
size: 18,
color: Colors.black54,
)
],
),
Text(
breed,
style: TextStyle(
fontSize: 12,
color: fadedBlack,
fontWeight: FontWeight.bold,
),
),
CustomText(
text: age + ' years',
fontSize: 12,
color: fadedBlack,
),
Row(
children: [
Icon(
Icons.location_pin,
size: 16,
color: primaryGreen,
),
SizedBox(
width: 5,
),
CustomText(
text: 'Distance: ' + distance + ' Km',
fontSize: 12,
color: fadedBlack,
),
],
)
],
),
),
)
],
),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: customShadow,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
bottomRight: Radius.circular(20),
),
),
),
Container(
width: size.width * 0.48,
child: Stack(
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
boxShadow: customShadow,
borderRadius: BorderRadius.circular(22),
),
margin: EdgeInsets.only(top: 50),
),
Align(
child: Hero(
tag: petId,
child: Image.network(
imagePath,
loadingBuilder: loadingNetworkImage,
),
),
),
],
),
)
],
),
);
}
以下方法与 selectedPetsCategories()
相关:
int selectedPetsCategory = 0;
void changePetsCategoryBorder(int index) {
selectedPetsCategory = index;
emit(AppChangePetsCategoryBorderState());
}
我该如何解决这个错误?
所以对于之前的错误,因为我必须在 init 中添加 changeCategoryModelState()
方法,同时在 blocProvider 中启动应用程序,所以我将 int position
参数设为可选参数并尝试添加方法 { {1}} 如下代码:
addAll
并像下面的代码一样在 main 中调用它:
void changeCategoryModelState({int position}) {
petModel = currentCategoryPets[position];
if (position == 4) getPetsData();
if (position == 5) getCatsData();
currentCategoryPets.addAll(pets);
emit(AppChangeCategoryModelState());
}
我发现以下错误:
return BlocProvider(
create: (BuildContext context) => AppCubit()
..getUserData()
..getCategoriesData()
..getPetsData()
..getCatsData()
..changeCategoryModelState()
..handleScroll(),
child: BlocConsumer<AppCubit, AppStates>(...),);
答案 0 :(得分:1)
这是正确的答案,然后只需删除参数并将changeCategoryModelState
方法更新为:
void changeCategoryModelState() {
if (selectedPetsCategory == 5) {
currentCategoryPets.clear();
currentCategoryPets.addAll(cats);
print(selectedPetsCategory.toString());
}
else if (selectedPetsCategory == 4) {
currentCategoryPets.clear();
currentCategoryPets.addAll(pets);
print(selectedPetsCategory.toString());
}
emit(AppChangeCategoryModelState());
}