【问题标题】:Flutter Riverpod : Problems fetching data from Firebase using RiverpodFlutter Riverpod:使用 Riverpod 从 Firebase 获取数据时出现问题
【发布时间】:2021-04-29 12:37:38
【问题描述】:

我正在从 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 
    );
  }
}

【问题讨论】:

    标签: firebase flutter listview riverpod


    【解决方案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 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,
      });
    }
    
        
    

    【讨论】:

    • 已改进。但是,product.length 为“0”,并且列表仍未显示在屏幕上。看起来你需要一些其他的逻辑。谢谢。
    • 查看上面编辑过的答案,也许它可以帮助你。但是,如果产品列表页面只是从 firebase 中提取所有产品,则不需要添加功能
    • 我根据您的建议对其进行了测试,它帮助我解决了问题。此外,第一个建议“autoDispose”很有用。但是,我不确定这是否是使用 Riverpod 的正确方法。此外, onRefresh 不起作用。我们正在为此做更多工作。谢谢。
    • 你是在说我的回答吗?因为我在把它放在这里和它的工作之前运行了它
    • 感谢您的回答。我根据您的建议对其进行了测试,并且成功了。这对我帮助很大。
    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 2021-02-26
    • 2021-10-03
    • 2020-11-11
    • 1970-01-01
    • 2022-11-21
    • 2021-05-03
    • 1970-01-01
    相关资源
    最近更新 更多