Flutter Riverpod:使用Riverpod从Firebase获取数据存在问题



我要从Getx改到Riverpod。因此,使用Riverpod从Firebase获取数据存在问题。

服务器上有两个产品数据。运行后,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
};
}
}
<<p>Riverpod提供者/strong>
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}');
});
}

ProductPage ListView

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 
);
}
}
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 result;
}
}
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,
});
}