Flutter Riverpod:使用 Riverpod 从 Firebase 获取数据时出现问题

Flutter Riverpod : Problems fetching data from Firebase using Riverpod

我正在从 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", 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("Whosebug 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,
  });
}