当我尝试在我的 flutter 应用程序中加载主屏幕时,出现此错误。
**错误:无法在此 Consumer Widget 上方找到正确的提供者
发生这种情况是因为您使用了不包含提供程序的
BuildContext
您的选择。
确保 Consumer 在您的 MultiProvider/Provider 下。 当您创建提供程序并尝试立即读取它时,通常会发生这种情况。**
主屏幕
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
HomeScreenState createState() => HomeScreenState();
}
@override
class HomeScreenState extends State<HomeScreen> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: ColorConstants.purpleLight,
title: const Text('Learn Hadith', style: TextStyle(color: Colors.white, fontSize: 20)),
),
body: Consumer<HomeProvider>(
builder: (context, HomeProvider db, _) {
switch (db.dataStatus) {
case DataStatus.Initial:
db.getCollections(context);
return SizedBox(height: SizeConfig.screenHeight, width: SizeConfig.screenWidth, child: circularProgressBar());
case DataStatus.Loading:
return SizedBox(height: SizeConfig.screenHeight, width: SizeConfig.screenWidth, child: circularProgressBar());
case DataStatus.Loaded:
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 3 / 2,
),
itemCount: db.collectionList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
if (index == 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HadithViewScreen(),
),
);
} else if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChaptersList(collectionId: db.collectionList[index].collectionId!),
),
);
}
},
child: CollectionGridItem(collectionDb: db.collectionList[index]),
);
},
);
case DataStatus.Failure:
return Center(child: Text('Error: Something went wrong}'));
}
},
),
);
}
}
class CollectionGridItem extends StatelessWidget {
final CollectionDb collectionDb;
const CollectionGridItem({super.key, required this.collectionDb});
@override
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(35.0),
),
color: ColorConstants.purpleLight,
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(' ${collectionDb.collectionNameEn}', style: const TextStyle(color: Colors.white, fontSize: 15)),
Text('${collectionDb.collectionNameUr}', style: const TextStyle(color: Colors.white, fontSize: 15)),
],
),
),
),
);
}
}
I understand that there's something wrong with the way I'm accessing the provider. I tried using the Builder widget as well but i got the same error. Please help how can I solve this?
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: ColorConstants.purpleLight,
title: const Text('Learn Hadith', style: TextStyle(color: Colors.white, fontSize: 20)),
),
body: Builder(
builder: (context) {
final homeProvider = Provider.of<HomeProvider>(context);
switch (homeProvider.dataStatus) {
case DataStatus.Initial:
case DataStatus.Loading:
return SizedBox(
height: SizeConfig.screenHeight,
width: SizeConfig.screenWidth,
child: circularProgressBar(),
);
case DataStatus.Loaded:
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 3 / 2,
),
itemCount: homeProvider.collectionList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
if (index == 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HadithViewScreen(),
),
);
} else if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChaptersList(collectionId: homeProvider.collectionList[index].collectionId!),
),
);
}
},
child: CollectionGridItem(collectionDb: homeProvider.collectionList[index]),
);
},
);
case DataStatus.Failure:
return Center(child: Text('Error: Something went wrong'));
}
},
),
);
}
每当你想在代码中使用 Provider 时,你需要在访问之前通知 Flutter 该 Provider 正在被使用。这意味着在使用 Consumer 小部件或任何方法访问您的 Provider 之前,您必须使用 Provider 包装祖先小部件之一。
单个小部件或页面的示例
如果您将 Provider 用于特定的小部件或页面,您可以像这样直接包装它:
Provider(
create: (_) => HomeProvider(),
child: YourWidget(),
)
使用多个提供商
对于较大的应用程序,建议使用MultiProvider同时创建和管理多个Provider。这样,您就可以在整个应用程序中使用它们。设置方法如下:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => HomeProvider()),
// Add other providers here if needed
],
child: MyApp(),
),
);
}
通过使用 MultiProvider 包装您的根小部件,您可以确保所有子小部件都可以访问指定的提供程序,从而使您的代码更干净且更易于维护。
使用提供者进行状态管理有很多值得探索的地方。为此,您可以随时参考官方文档这里。