Flutter Provider 仅在热重载后显示结果

Posted

技术标签:

【中文标题】Flutter Provider 仅在热重载后显示结果【英文标题】:Flutter Provider showing results ONLY after Hot Reload 【发布时间】:2021-02-06 10:17:36 【问题描述】:

我是初学者,我正在按照使用提供程序的教程构建应用程序。逻辑是,当您单击“类别”小部件时,它应该会引导您进入包含该类别产品的页面。逻辑按预期工作,除了我必须先刷新代码才能显示结果。坦率地说,我不知道自己做错了什么。

在主页中,类别小部件使用列表视图构建器呈现

Container(
                height: 75,
                child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: categoryProvider.categories.length,
                  itemBuilder: (context, index) 
                    return GestureDetector(
                      onTap: () async 
                        await productProvider.loadProductsByCategory(
                            categoryName:
                                categoryProvider.categories[index].name);
                        changeScreen(
                            context,
                            CategoryScreen(
                                categoryModel:
                                    categoryProvider.categories[index]));
                      ,
                      child: CategoriesWidget(
                          category: categoryProvider.categories[index]),
                    );
                  ,
                ),
              )

Main.Dart

我在听这样的供应商

void main() 
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: AppProvider()),
        ChangeNotifierProvider.value(value: UserProvider.initialize()),
        ChangeNotifierProvider.value(value: CategoryProvider.initialize()),
        ChangeNotifierProvider.value(value: MarketProvider.initialize()),
        ChangeNotifierProvider.value(value: ProductProvider.initialize()),
      ],
      child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Akatale',
          theme: ThemeData(
            primaryColor: Colors.black,
          ),
          home: ScreenController())));


class ScreenController extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final auth = Provider.of<UserProvider>(context);

    switch (auth.status) 
      case Status.Uninitialized:
        return Loading();
      case Status.UnAuthenticated:
      case Status.Authenticating:
        return SignInScreen();
      case Status.Authenticated:
        return MainScreen();
      default:
        return SignInScreen();
    
  

产品服务

有了这个,我按类别名称从 firestore 获取产品并将它们添加到列表中

class ProductService extends ChangeNotifier 
  String collection = "products";
  Firestore _firestore = Firestore.instance;


  Future<List<ProductModel>> getProductsByCategory(String category) async 
    List<ProductModel> products = [];
    _firestore
        .collection(collection)
        .where("category", isEqualTo: category)
        .getDocuments()
        .then((result) 
      for (DocumentSnapshot product in result.documents) 
        products.add(ProductModel.fromSnapshot(product));
      
    );
    return products;
  

产品供应商

这里我有要在小部件中调用的公共方法

class ProductProvider with ChangeNotifier 
  ProductService _productService = ProductService();
  List<ProductModel> products = [];
  List<ProductModel> productsByCategory = [];


  ProductProvider.initialize() 
    _loadProducts();
   
  

  //Private method Load products to List
  Future _loadProducts() async 
    products = await _productService.getProducts();
    notifyListeners();
  

  //public method to Load products to List by category
  Future loadProductsByCategory(String categoryName) async 

    productsByCategory =
        await _productService.getProductsByCategory(category: categoryName);

    notifyListeners();
  

分类页面

这是根据所选类别呈现产品的位置

class CategoryScreen extends StatelessWidget 
  final CategoryModel categoryModel;

  const CategoryScreen(Key key, this.categoryModel) : super(key: key);
  @override
  Widget build(BuildContext context) 
    final productProvider = Provider.of<ProductProvider>(context);
    return Scaffold(
      body: SafeArea(
          child: ListView(
        children: [
          Text(categoryModel.name),
          Column(
            children: productProvider.productsByCategory.map((item) 
              return GestureDetector(
                  onTap: () 
                    //Load details page
                  ,
                  child: ProductWidget(
                    product: item,
                  ));
            ).toList(),
          ),
        ],
      )),
    );
  

显示一个空白页

但在点击热重载时,产品会出现

【问题讨论】:

如果我错了,请纠正我,但是通过浏览您的代码,我没有找到监听 ProductProvider 的小部件 你是对的。如果我认为是您的意思,我已经编辑了问题以添加该问题。我在 main.dart 文件中这样做 【参考方案1】:

在您的ProductsService 中的getProductsByCategory 中,您不会等待getDocuments。 因此,虽然文档将被加载,但它已经在模型中调用 notifyListeners,然后才真正完成加载它们。 因此,当您使用 hotreload 进行重建时,它们会出现

要解决这个问题,只需等待服务中的 getDocuments

【讨论】:

以上是关于Flutter Provider 仅在热重载后显示结果的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:应用程序在热重载后不断回到初始路线

颤振:使用提供程序时,状态在热重载时丢失

Flutter:未处理的异常:无法加载资产

标记不会在 Flutter 中显示

StreamBuilder 仅在热重启后更新流

使用提供程序包 FLUTTER 关闭应用程序后保存状态