Flutter: как запрашивать элементы списка с помощью GetX

Я пытаюсь фильтровать по категории, но на каждой странице категории отображаются все продукты, но я хочу фильтровать по странице категории, пожалуйста, проверьте мой код и дайте мне знать, как я могу это сделать.

      class CategoryNavigationController extends GetxController {
  TabController tabController;

  final List<CategoryModel> _categories = allCategories;

  List<CategoryModel> get allCategory => _categories;

  int currentCategoryIndex;
  String currentCategoryTitle;
  List<Widget> totalCategoryTabs = [];
  List<ProductModel> _filtertedProducts;
  Widget currentTab;

  @override
  void onInit() {
    super.onInit();
    totalCategoryTabs = List.generate(allCategory.length, (index) {
      return ProductCardList(
        totalProducts: 1,
        productName: "WHy",
        productImage: "assets/images/chicken.png",
        price: "150",
        scrollDirection: Axis.vertical,
      );
    });
  }

  void selectCategory(int index) {
    currentCategoryIndex = index;
    currentCategoryTitle = allCategory[index].categoryName;
    _filterProductData(currentCategoryTitle);
    currentTab = totalCategoryTabs[index];
    Get.to(() => CategoryScreen());
    update();
  }

  void changeTab(int index) {
    currentCategoryIndex = index;
    currentCategoryTitle = allCategory[currentCategoryIndex].categoryName;
    _filterProductData(currentCategoryTitle);
    currentTab = totalCategoryTabs[currentCategoryIndex];
    update();
  }

  void _filterProductData(query) {
    print(query);
  }
}

1 ответ

Решение

Хорошо, для начала давайте рассмотрим это:

      final List<CategoryModel> _categories = allCategories;

List<CategoryModel> get allCategory => _categories;

Это не делает ничего ценного. Вы объявляете частную переменную и инициализируете ее глобальной переменной верхнего уровня. Затем использование общедоступного геттера для доступа к частной переменной, которая снова является не чем иным, как уже объявленной вами глобальной переменной.

Итак, здесь 2 вещи.

  1. Я контрастирую с другими языками, в Dart ничего не получится от использования геттеров и сеттеров, ЕСЛИ вы не добавляете настраиваемую логику для получения или установки значения.

  2. Нет причин, по которым allCategories  список должен быть глобальным. Вы можете просто поместить его в класс GetX, и он по-прежнему очень легко доступен из любой точки приложения. Так что давайте упростим это и просто поместим этот список в класс и потеряем геттеры. Теперь это одна переменная вместо трех.

Как правило, лучше не делать этого, если нет веской причины сделать что-то глобальное.

Что касается фактического решения. Есть разные способы добиться этого, но я бы сделал это следующим образом:

Вместо того, чтобы фильтровать список и перестраивать все каждый раз, я просто настраиваю отдельный список для каждой категории, и функция добавляет его в нужный список в зависимости от категории. Таким образом, единственное, что будет перестроено, - это соответствующая вкладка. Я оставил основной список продуктов на случай, если он понадобится вам для чего-то еще, но он не используется ни для чего, что я здесь делаю.

        List<ProductModel> masterProductList = [];

  List<ProductModel> chickenList = [];
  List<ProductModel> fishList = [];
  List<ProductModel> muttonList = [];
  List<ProductModel> marinadeList = [];
  List<ProductModel> coldCutList = [];
  List<ProductModel> proneList = [];

Кроме того, функция использует tabController(который выглядит так, как будто вы удалили, но я вернул его), чтобы перейти на соответствующую вкладку. Это может быть, а может и не быть желаемым поведением, но это просто показать вам очень простой способ управления вкладками с помощью Getx. В animateToфункция не является специфической для GetX, но легко разделять контроллер вкладок во всем вашем приложении. Вот функция, которая входит в ваш класс GetX.

Если у вас есть обширный список продуктов, о котором я не знаю, вы все равно можете просмотреть его и передать все через эту функцию, и она отсортирует его.

      void addProduct(ProductModel product) {
    masterProductList.add(product);
    switch (product.category.categoryName) {
      case 'Chicken':
        chickenList.add(product);
        tabController.animateTo(0); // this jumps to whatever tab you want based on the index you pass in
        break;
      case 'Fish':
        fishList.add(product);
        tabController.animateTo(1);
        break;
      case 'Mutton':
        muttonList.add(product);
        tabController.animateTo(2);
        break;
      case 'Marinade':
        marinadeList.add(product);
        tabController.animateTo(3);
        break;
      case 'Cold Cut':
        coldCutList.add(product);
        tabController.animateTo(4);
        break;
      case 'Prone':
        proneList.add(product);
        tabController.animateTo(5);
        break;
    }
    update();
  }

Поскольку у меня нет всего вашего кода пользовательского интерфейса, вот значительно упрощенная версия, чтобы показать вам, как это работает. Вы можете реализовать это в своем приложении, как считаете нужным.

Вот TabHome. Здесь ничего не восстанавливается, это всего лишь узел для вкладок. В GetView<CategoryNavigationController> это просто виджет без сохранения состояния, который избавляет нас от необходимости искать этот контроллер на этой странице.

      class TabHome extends GetView<CategoryNavigationController> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: controller.allCategories.length,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: controller.totalCategoryTabs,
            controller: controller.tabController,
          ),
          title: Text('Categories'),
        ),
        body: TabBarView(
          controller: controller.tabController,
          children: [
            ProductPage(list: controller.chickenList), // passing in corresponding list from GetX class
            ProductPage(list: controller.fishList),
            ProductPage(list: controller.muttonList),
            ProductPage(list: controller.marinadeList),
            ProductPage(list: controller.coldCutList),
            ProductPage(list: controller.proneList),
          ],
        ),
      ),
    );
  }
}

Вот очень простая страница продукта, которая передается в виде списка, который передается в ListView.builder в пределах GetBuilder виджет.

      class ProductPage extends StatelessWidget {
  final List list;

  const ProductPage({Key key, this.list}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          GetBuilder<CategoryNavigationController>(
            builder: (controller) => Expanded(
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (context, index) => ProductRow(product: list[index]),
              ),
            ),
          ),
          ButtonRow(),
        ],
      ),
    );
  }
}

Очень простой Row это требует ProductModel

      class ProductRow extends StatelessWidget {
  final ProductModel product;

  const ProductRow({Key key, this.product}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Row(children: [Text(product.productName)]);
  }
}

В ButtonRow что вы видите в ProductPage - это виджет, 6 из которых добавляют товар из другой категории, вызывая одно и то же addProduct функция, но добавление другого продукта.

       Expanded(
              child: ElevatedButton(
                onPressed: () {
                  controller.addProduct(
                    ProductModel(
                      productName: 'boneless chicken',
                      category: CategoryModel(categoryName: 'Chicken'),
                    ),
                  );
                },
                child: Text('Add chicken'),
              ),
            ),

И, наконец, пара небольших изменений в вашем onInit. Не забудьте добавить with SingleGetTickerProviderMixin в ваш класс GetX, что позволяет вам работать с анимацией и контроллерами вкладок в виджетах без сохранения состояния.

        @override
  void onInit() {
    super.onInit();
    totalCategoryTabs = List.generate(allCategories.length, (index) {
      return ProductCardList(
        totalProducts: 1,
        productName: allCategories[index].categoryName, // auto names your tabs based on allCategories list
        productImage: "assets/images/chicken.png",
        price: "150",
        scrollDirection: Axis.vertical,
      );
    });
    tabController =
        TabController(length: totalCategoryTabs.length, vsync: this); // made possible with SingleGetTickerProviderMixin 
  }

А вот и небольшая демонстрация. Графический интерфейс не очень привлекателен, но идею вы поняли.

Другие вопросы по тегам