Я учусь использовать провайдеров в своем приложении Flutter, которые обмениваются данными с базой данных Firestore.
Первоначально приложение загружало мои документы из коллекции firestore в ProductPage в виджете Listview, а нажатием на ListTile вы могли редактировать документ или удалите его. Кроме того, на панели приложений есть кнопка, с которой пользователь может добавить продукт. Это сработало.
Затем я добавил поток аутентификации в приложение, которое в настоящее время работает. Но чтобы слушать authChanges во всем приложении, мне пришлось изменить способ работы исходного провайдера со страницы main.dart.
Я изменил свой код с
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
final firestoreService = FirestoreService();
return MultiProvider(
providers: [
ChangeNotifierProvider( create: (context)=> ProductController(),),
StreamProvider(create: (context) => firestoreService.fetchAllProducts())
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Authenticate(),
),
);
}
}
и изменил его на: Main.dart code:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Wrapper(),
),
);
}
}
Мне удалось соединить все вместе таким образом, что после аутентификации пользователь может получить доступ к продуктам.
Продукты извлекаются, как ожидалось, однако теперь при попытке перейти на editPage
Navigator.of(context).push(
CupertinoPageRoute(
builder: (context) => EditProduct(),
),
или на страницу нового продукта
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(products[index].productName),
trailing: Text(products[index].price.toString()),
onTap: () {
**Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => EditProduct(products[index])**,
),
);
},
);
})
, выдается ошибка
Error: Could not find the correct Provider<ProductController> above this EditProduct Widget
Код Wrapper.dart:
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final firestoreService = FirestoreService();
final user = Provider.of<User>(context);
//return either Products Page or Authentication Page
if (user == null) {
return Authenticate();
}
else {
// return StreamProvider(
// create: (context) => firestoreService.fetchAllProducts(),
// child: Products(),
// );
return MultiProvider(
providers: [
ChangeNotifierProvider<ProductController>( create: (context)=> ProductController(),),
StreamProvider(create: (context) => firestoreService.fetchAllProducts())
],
child: Consumer<ProductController>(builder: (context, provider, child) =>Products()) ,
);
}
}
}
Страница продуктов:
@override
Widget build(BuildContext context) {
final products = Provider.of<List<Product>>(context);
return Scaffold(
appBar: AppBar(
...button that leads to editPage..
Navigator.of(context).push(
CupertinoPageRoute(
builder: (context) => EditProduct(),
),
);
},
),
],
),
body:
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(products[index].productName),
trailing: Text(products[index].price.toString()),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => EditProduct(products[index]),
),
);
},
);
})
);
}
}
Редактировать / Добавить продукт Конструктор страниц
Widget build(BuildContext context) {
final productController = Provider.of<ProductController>(context);
return Scaffold(.....more widgets....);