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
    };
  }
}

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