首页 > 解决方案 > 在搜索委托 buildResults() 中使用 setstate() ..?

问题描述

我正在使用颤振显示搜索()和由 SearchDelegate 扩展的类。我将我的类对象列表传递给委托类。在 buildResult() 方法中,我需要创建一个自定义列表视图。每个列表视图属性都需要更改其底层小部件。但我不能在 buildResults() 函数中使用 setstate(),因为它没有构建器。这是我的代码。希望这一切都有意义。仅供参考,它可以简单地搜索在线商店的产品。

import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:rashan/models/order.dart';
import 'package:rashan/models/product.dart';

class ProductScreen extends StatefulWidget {
  static final String id = "product_screen";
  final String category;
  final String subCategory;

  ProductScreen({
    @required this.category,
    @required this.subCategory,
  });

  @override
  _ProductScreenState createState() => _ProductScreenState();
}

class _ProductScreenState extends State<ProductScreen> {
  final productList = <Product>[];

  @override
  void initState() {
    super.initState();
    FirebaseDatabase.instance
        .reference()
        .child("Data")
        .child("All Products")
        .child(widget.category)
        .child(widget.subCategory)
        .once()
        .then((snapshot) {
      setState(() {
        var result = snapshot.value.values as Iterable;
        for (var item in result) {
          var product = Product(
              id: item['id'],
              name: item['name'],
              image: item['image'],
              price: item['price'],
              quantity: item['quantity'],
              category: item['category'],
              subCategory: item['subCategory']);
          productList.add(product);
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        centerTitle: true,
        leading: IconButton(
          icon: Icon(
            Icons.arrow_back,
            color: Colors.black,
          ),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
        title: Text(
          "Rashan",
          style: TextStyle(
              color: Theme.of(context).primaryColor,
              fontSize: 48.0,
              fontFamily: "Billabong"),
        ),
        actions: <Widget>[
          productList.length != 0
              ? IconButton(
                  icon: Icon(
                    Icons.search,
                    color: Colors.black,
                  ),
                  onPressed: () {
                    showSearch(
                        context: context, delegate: ProductSearch(productList));
                  },
                )
              : Container()
        ],
      ),
      body: Center(
        child: Container(
            child: productList.length == 0
                ? Text(
                    "Loading Products ...!",
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: Theme.of(context).primaryColor,
                        fontSize: 16.0,
                        fontWeight: FontWeight.w500),
                  )
                : ListView.builder(
                    itemCount: productList.length,
                    itemBuilder: (BuildContext context, int index) {
                      return productUI(productList[index]);
                    },
                  )),
      ),
    );
  }

  Widget productUI(Product product) {
    String _price = product.price;
    var order = new Order();
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      color: Colors.white,
      elevation: 5.0,
      margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
      child: Container(
        padding: EdgeInsets.all(5.0),
        child: Row(
          children: <Widget>[
            Container(
              height: 120.0,
              width: 120.0,
              child: Image.network(product.image),
            ),
            SizedBox(
              width: 10.0,
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Container(
                    margin: EdgeInsets.only(top: 5.0),
                    padding: EdgeInsetsDirectional.only(end: 4.0),
                    child: Text(
                      product.name,
                      style: TextStyle(
                          fontSize: 20.0, fontWeight: FontWeight.w600),
                    ),
                  ),
                  SizedBox(
                    height: 10.0,
                  ),
                  Text(product.category),
                  Text(product.subCategory),
                  Text(
                    'Price: Rs $_price ',
                    style: TextStyle(
                        color: Theme.of(context).primaryColor,
                        fontSize: 16.0,
                        fontWeight: FontWeight.w500),
                  ),
                  SizedBox(
                    height: 10.0,
                  ),
                  Container(
                    margin:
                        EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
                    height: 40.0,
                    color: Theme.of(context).primaryColor,
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        GestureDetector(
                          onTap: () {
                            setState(() {
                              order.decrementQuantity(product.id);
                            });
                          },
                          child: Container(
                            height: 50.0,
                            width: 50.0,
                            child: Icon(
                              Icons.remove,
                              color: Colors.white,
                            ),
                          ),
                        ),
                        Expanded(
                          child: Center(
                              child: Text(
                            order.getQuantity(product.id) == 0
                                ? "Add to Cart"
                                : order.getQuantity(product.id).toString(),
                            style: TextStyle(color: Colors.white),
                          )),
                        ),
                        GestureDetector(
                          onTap: () {
                            setState(() {
                              order.addOrIncrement(product.id);
                            });
                          },
                          child: Container(
                            height: 50.0,
                            width: 50.0,
                            child: Icon(
                              Icons.add,
                              color: Colors.white,
                            ),
                          ),
                        )
                      ],
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

class ProductSearch extends SearchDelegate<Product> {
  List<Product> _productList;

  ProductSearch(this._productList);

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          icon: Icon(
            Icons.clear,
          ),
          onPressed: () {
            query = '';
          })
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: Icon(
          Icons.arrow_back,
        ),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    List<Product> searchResult = [];
    for (var product in _productList) {
      if (query.isNotEmpty && product.name.toLowerCase().contains(query)) {
        searchResult.add(product);
        print(product.name);
      }
    }
    return Container(
      child: ListView.builder(
        itemCount: searchResult.length,
        itemBuilder: (BuildContext context, int index) {
          return productUI(context, searchResult[index]);
        },
      ),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return Container();
  }

  Widget productUI(BuildContext context, Product product) {
    String _price = product.price;
    var order = new Order();
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10.0),
      ),
      color: Colors.white,
      elevation: 5.0,
      margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
      child: Container(
        padding: EdgeInsets.all(5.0),
        child: Row(
          children: <Widget>[
            Container(
              height: 120.0,
              width: 120.0,
              child: Image.network(product.image),
            ),
            SizedBox(
              width: 10.0,
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Container(
                    margin: EdgeInsets.only(top: 5.0),
                    padding: EdgeInsetsDirectional.only(end: 4.0),
                    child: Text(
                      product.name,
                      style: TextStyle(
                          fontSize: 20.0, fontWeight: FontWeight.w600),
                    ),
                  ),
                  SizedBox(
                    height: 10.0,
                  ),
                  Text(product.category),
                  Text(product.subCategory),
                  Text(
                    'Price: Rs $_price ',
                    style: TextStyle(
                        color: Theme.of(context).primaryColor,
                        fontSize: 16.0,
                        fontWeight: FontWeight.w500),
                  ),
                  SizedBox(
                    height: 10.0,
                  ),
                  Container(
                    margin:
                        EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
                    height: 40.0,
                    color: Theme.of(context).primaryColor,
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        GestureDetector(
                          onTap: () {
                            // setState(() {
                              order.decrementQuantity(product.id);
                            // });
                          },
                          child: Container(
                            height: 50.0,
                            width: 50.0,
                            child: Icon(
                              Icons.remove,
                              color: Colors.white,
                            ),
                          ),
                        ),
                        Expanded(
                          child: Center(
                              child: Text(
                            order.getQuantity(product.id) == 0
                                ? "Add to Cart"
                                : order.getQuantity(product.id).toString(),
                            style: TextStyle(color: Colors.white),
                          )),
                        ),
                        GestureDetector(
                          onTap: () {
                            // setState(() {
                              order.addOrIncrement(product.id);
                            // });
                          },
                          child: Container(
                            height: 50.0,
                            width: 50.0,
                            child: Icon(
                              Icons.add,
                              color: Colors.white,
                            ),
                          ),
                        )
                      ],
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

标签: fluttersetstate

解决方案


如果你想为每个列表项设置一个状态,你可以只创建一个StatefulWidget而不是使用方法productUI()。如果您想从上层 Widget (List) 控制状态,则只需StatefulWidget为该级别创建一个。

class ProductUi extends StatefulWidget {
  final Product product;

  ProductScreen(@required this.product) : assert(product != null);

  @override
  _ProductUiState createState() => _ProductUiState();
}

class _ProductUiState extends State<ProductUi> {
  @override
  Widget build(BuildContext context) => productUI(context, widget.product);

  Widget productUI(BuildContext context, Product product) {
  // ...
  // now you can setState from taps and delegates
  }
}

推荐阅读