You need to enable JavaScript to run this app. 基于GetX保留现有Controller与UI,如何动态修改API参数拉取不同产品数据
优惠活动
大模型
产品
解决方案
定价
更多

基于GetX保留现有Controller与UI,如何动态修改API参数拉取不同产品数据

动态分类拉取实现方案

服务层调整(仅修改硬编码分类值)

原ProductServices.fetchProducts为静态无参方法,内部硬编码分类值4,仅给方法新增分类入参,替换硬编码值,其余请求、解析、错误判断逻辑完全保留:

class ProductServices {
  static var client = http.Client();

  // 新增category入参,方法主体逻辑不做任何改动
  static Future fetchProducts(String category) async {
    var response = await client.post(
        Uri.https('********.com', 'api/getProduct'),
        // 替换原硬编码的"4"为动态传入的category值
        body:'{"category":"$category","search":"","sortBy":"relavance","page":"","size":""}');
    if (response.statusCode == 200) {
      var jsonString = response.body;
      print(productsScreenFromJson(jsonString));
      return productsScreenFromJson(jsonString);
    } else {
      return null;
    }
  }
}

Controller层调整(不改动原有核心结构)

原ProductController的响应式列表、生命周期、数据赋值逻辑全部保留,仅新增分类存储逻辑,给拉取方法加可选入参,不破坏原有首次加载流程:

import 'package:get/state_manager.dart';
import 'package:get_it_test/services/product_services.dart';

class ProductController extends GetxController {
  // 原有响应式列表完全保留,无任何修改
  var ProductList = [].obs;
  // 新增响应式变量存储当前生效的分类值,默认值设为原硬编码的4,不影响首次加载行为
  var currentCategory = "4".obs;

  @override
  void onInit() {
    // 首次加载逻辑和原实现完全一致,调用拉取方法传入当前分类
    fetchProduct(category: currentCategory.value);
    super.onInit();
  }

  // 原fetchProduct方法仅增加可选命名参数,内部拉取、赋值逻辑不做改动
  void fetchProduct({String? category}) async {
    // 如果传入了新的分类值,同步更新存储的当前分类
    if (category != null) currentCategory.value = category;
    // 调用服务层时传入当前分类值,替换原无参调用逻辑
    var productsList = await ProductServices.fetchProducts(currentCategory.value); 
    print(productsList.data.products);
    if (productsList != null) {
      ProductList.assignAll(productsList.data.products);
    }
  }
}

UI层调整(不改动原有页面结构)

原页面的列表渲染、Obx监听、底部栏布局逻辑全部保留,仅调整Controller的获取时机,解决初始化器无法访问实例成员的编译告警:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_it_test/Views/Widgets/BottomBar.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:get_it_test/Controller/product_controller.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

class ProductScreen extends StatelessWidget {
  // 原有title参数保留
  final String title;
  // 新增可选参数接收页面跳转时传入的初始分类,默认值为原硬编码4,不破坏原有页面调用方式
  final String initialCategory;

  // 构造函数适配新增参数,无强制传参要求
  ProductScreen({this.title = "", this.initialCategory = "4"});

  // 把原字段级的Get.put声明改为懒加载声明,解决初始化器阶段无法访问实例成员的问题
  late final ProductController productController;

  @override
  Widget build(BuildContext context) {
    // 在build方法内完成Controller的获取/注册,此时已可正常访问页面实例成员
    productController = Get.put(ProductController());
    // 若传入的初始分类和Controller默认值不一致,触发一次对应分类的数据拉取,不影响原有页面布局
    if (productController.currentCategory.value != initialCategory) {
      productController.fetchProduct(category: initialCategory);
    }

    return Scaffold(
      // 以下所有原有UI代码完全保留,无任何改动
      appBar: AppBar(
        iconTheme: IconThemeData(color: Colors.black),
        backgroundColor: Colors.white,
        title: Text(
          title,
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: Obx(() => StaggeredGridView.countBuilder(
                    crossAxisCount: 2,
                    itemCount: productController.ProductList.length,
                    itemBuilder: (BuildContext context, int index) =>
                        new Container(
                            width: 200,
                            child: Padding(
                              padding: const EdgeInsets.all(8.0),
                              child: Column(
                                children: [
                                  CachedNetworkImage(
                                    imageUrl: productController
                                        .ProductList[index].image,
                                    placeholder: (context, url) =>
                                        new CircularProgressIndicator(),
                                    errorWidget: (context, url, error) => new Image
                                            .network(
                                        '****.com/noimage.png'),
                                  ),
                                  Text(productController
                                      .ProductList[index].prodName),
                                ],
                              ),
                            )),
                    staggeredTileBuilder: (int index) =>
                        new StaggeredTile.fit(1),
                    mainAxisSpacing: 4.0,
                    crossAxisSpacing: 4.0,
                  )),
            ),
            BottomBar()
          ],
        ),
      ),
    );
  }
}

按钮触发动态拉取的用法

页面上的分类按钮,在原有点击事件中仅需加一行调用即可实现数据切换,按钮的布局、样式、交互逻辑完全不需要修改:

// 示例:分类按钮的点击事件
onPressed: () {
  // 传入对应分类的数字字符串,即可自动拉取对应分类的产品,列表会因Obx监听自动刷新
  productController.fetchProduct(category: "对应的分类号");
}

内容的提问来源于stack exchange,提问作者Aryan Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.29 20:24:02