#firebase #flutter #listview #riverpod
#firebase #flutter #listview #riverpod
Вопрос:
Я перехожу с Getx на Riverpod. Итак, проблемы с выборкой данных из Firebase с использованием Riverpod.
У меня есть данные о двух продуктах на сервере. Первоначально после запуска страница ProductListPage ничего не показывает. Введите страницу еще раз, и отобразится список. И каждый раз, когда вы вводите, список накапливается. Как получить данные с сервера с помощью Riverpod?
Модель
class Product {
String id;
String name;
String category;
String image;
String images;
String desc;
String price;
Timestamp createdAt;
Timestamp updatedAt;
Product();
Product.fromMap(Map<String, dynamic> data) {
id = data['id'] ?? "ID Data Null";
name = data['name'] ?? "Name Data Null";
category = data['category'] ?? "Category Data Null";
image = data['image'] ?? "Image Data Null";
//images = data['images'];
desc = data['desc'] ?? "Desc Data Null";
price = data['price'] ?? "Price Data Null";
createdAt = data['createdAt'];
updatedAt = data['updatedAt'];
}
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'category': category,
'images': images,
'image': image,
'desc': desc,
'price': price,
'createdAt': createdAt,
'updatedAt': updatedAt
};
}
}
Поставщик Riverpod
final productListProvider = StateNotifierProvider<ProductList>((ref) {
return ProductList();
});
class ProductList extends StateNotifier<List<Product>> {
//static Product productModel = Product();
ProductList([List<Product> state]) : super(state ?? []);
productAdd(Product product) {
state.add(product);
}
Future<void> refreshList() async {
getStateProducts();
}
getStateProducts() async {
QuerySnapshot snapshot = await FirebaseFirestore.instance
.collection('Products')
.get();
snapshot.docs.forEach((document) {
Product _product = Product.fromMap(document.data());
productAdd(_product);
print('DataBase: ${_product.name}');
});
}
Список страниц продукта
class ProductListPage extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final productObj = watch(productListProvider);
final product = watch(productListProvider.state);
productObj.getStateProducts(); //
return Scaffold(
appBar: AppBar(
title: Text('Product List'),
),
body: new RefreshIndicator(
child: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Image.network(
product[index].image != null
? product[index].image
: 'https://www.testingxperts.com/wp-content/uploads/2019/02/placeholder-img.jpg',
width: 120,
fit: BoxFit.fitWidth,
),
title: Text(product[index].name),
subtitle: Text(product[index].category),
onTap: () {
// getxController.currentIndex(index);
// getxController.currentProduct =
// getxController.productList[index];
// return Get.to(ProductDetail(), arguments: "test");
},
);
},
itemCount: product.length,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: Colors.black,
);
},
),
onRefresh: productObj.refreshList), // Refresh
);
}
}
Ответ №1:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/all.dart';
List<Product> productList = [
Product(category: "categoryA", id: "0010", name: "ProductA"),
Product(category: "categoryB", id: "0010", name: "ProductB"),
Product(category: "categoryC", id: "0011", name: "ProductC"),
Product(category: "categoryD", id: "0011", name: "ProductD"),
];
final productListStateProvider =
StateNotifierProvider((ref) => ProductListState());
class ProductListState extends StateNotifier<AsyncValue<List<Product>>> {
ProductListState([AsyncValue<List<Product>> state])
: super(state ?? AsyncValue.data(<Product>[]));
Future<List<Product>> getStateProducts() async {
state = AsyncValue.loading();
await Future.delayed(Duration(seconds: 2));
final result = productList;
state = AsyncValue.data(productList);
return resu<
}
}
class ProductsPage extends StatefulWidget {
@override
_ProductsPageState createState() => _ProductsPageState();
}
class _ProductsPageState extends State<ProductsPage> {
@override
void initState() {
context.read(productListStateProvider).getStateProducts();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Stackoverflow answer"),
),
body: Container(
child: RefreshIndicator(
onRefresh: () =>
context.read(productListStateProvider).getStateProducts(),
child: ProductListWidget()
),
),
);
}
}
class ProductListWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final resultData = watch(productListStateProvider.state);
return resultData.maybeWhen(
data: (results) => ListView.builder(
itemCount: results.length,
itemBuilder: (context, index) {
final product = results[index];
return ListTile(
title: Text(product.name),
subtitle: Text(product.category),
);
}),
loading: () => Center(child: CircularProgressIndicator()),
error: (er, st) => Center(child: Text("Error occurred")),
orElse: () => Text("No data yet"));
}
}
@immutable
class Product {
final String id;
final String name;
final String category;
final String image;
final String images;
final String desc;
final String price;
final dynamic createdAt;
final dynamic updatedAt;
Product({
this.id,
this.name,
this.category,
this.image,
this.images,
this.desc,
this.price,
this.createdAt,
this.updatedAt,
});
}
Комментарии:
1. Улучшено. Тем не менее, продукт. длина равна ‘0’, и список по-прежнему не отображается на экране. Похоже, вам нужна какая-то другая логика. Спасибо.
2. проверьте отредактированный ответ выше, возможно, это может вам помочь. Однако нет необходимости в функции добавления, если страница списка продуктов просто извлекает все продукты из firebase
3. Я протестировал его с вашим предложением, и это помогло мне решить проблему. Кроме того, первое предложение «Автоматическое удаление» было полезным. Однако я не уверен, что это правильный способ использования Riverpod. Кроме того, onRefresh не работает. Мы работаем над этим дальше. Спасибо.
4. вы говорите о моем ответе? потому что я запустил его перед размещением здесь, и он работает
5. Спасибо за ваш ответ. Я протестировал его относительно вашего предложения, и оно успешно сработало. Это мне очень помогает.