问题描述
我正在从 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
};
}
}
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
);
}
}
解决方法
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/all.dart';
List<Product> productList = [
Product(category: "categoryA",id: "0010",name: "ProductA"),Product(category: "categoryB",name: "ProductB"),Product(category: "categoryC",id: "0011",name: "ProductC"),Product(category: "categoryD",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,});
}