You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter GetX控制器初始化报错:无法通过Get.find()获取PopularProductController

Flutter GetX控制器初始化问题解决方案

问题描述

在Flutter项目对接JSON API时,使用GetX依赖注入初始化PopularProductController后,在main.dart中调用Get.find<PopularProductController>().getPopularProductList()时出现找不到控制器的错误,提示需要调用Get.put或Get.lazyPut。

相关代码文件

depencies.dart

import 'package:food_delivery/controllers/popular_product_controller.dart';
import 'package:food_delivery/data/api/apiclient.dart';
import 'package:food_delivery/data/repository/popular_product_repo.dart';
import 'package:get/get.dart';

Future<void> init() async {
  //api clinet
  Get.lazyPut(() => ApiClient(appBaseUrl: 'https://mvs.bslmeiyu.com'));

  //repository
  Get.lazyPut(() => PopularProductRepo(apiClient: Get.find()));

  //controllers
  Get.lazyPut(() => PopularProductController(popularProductRepo: Get.find()));
}
import 'package:food_delivery/data/api/apiclient.dart';
import 'package:get/get.dart';

class PopularProductRepo extends GetxService {
  final ApiClient apiClient;

  PopularProductRepo({required this.apiClient});

  Future<Response> getPopularProductList() async {
    return await apiClient
        .getData('http://mvs.bslmeiyu.com/api/v1/products/popular');
  }
}
import 'package:food_delivery/data/repository/popular_product_repo.dart';
import 'package:food_delivery/models/products_model.dart';
import 'package:get/get.dart';

class PopularProductController extends GetxController {
  final PopularProductRepo popularProductRepo;

  PopularProductController({required this.popularProductRepo});

  List<dynamic> _popularProductList = [];
  List<dynamic> get popularProductList => _popularProductList;

  Future<void> getPopularProductList() async {
    Response response = await popularProductRepo.getPopularProductList();
    if (response.statusCode == 200) {
      _popularProductList = [];
      _popularProductList.addAll(Product.fromJson(response.body).products);
      update();
    } else {
      return null;
    }
  }
}

product_model.dart

class Product {
  int? _totalSize;
  int? _typeId;
  int? _offset;
  late List<ProductModel> _products;
  List<ProductModel> get products => _products;

  Product(
      {required totalSize,
      required typeId,
      required offset,
      required products}) {
    this._totalSize = totalSize;
    this._typeId = typeId;
    this._offset = offset;
    this._products = products;
  }

  Product.fromJson(Map<String, dynamic> json) {
    _totalSize = json['total_size'];
    _typeId = json['type_id'];
    _offset = json['offset'];
    if (json['products'] != null) {
      _products = <ProductModel>[];
      json['products'].forEach((v) {
        _products!.add(ProductModel.fromJson(v));
      });
    }
  }
}

class ProductModel {
  int? id;
  String? name;
  String? description;
  int? price;
  int? stars;
  String? img;
  String? location;
  String? createdAt;
  String? updatedAt;
  int? typeId;

  ProductModel(
      {this.id,
      this.name,
      this.description,
      this.price,
      this.stars,
      this.img,
      this.location,
      this.createdAt,
      this.updatedAt,
      this.typeId});

  ProductModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    description = json['description'];
    price = json['price'];
    stars = json['stars'];
    img = json['img'];
    location = json['location'];
    createdAt = json['created_at'];
    updatedAt = json['updated_at'];
    typeId = json['type_id'];
  }
}

apiclient.dart

import 'package:get/get.dart';

class ApiClient extends GetConnect implements GetxService {
  late String token;
  final String appBaseUrl;

  late Map<String, String> _mainHeaders;

  ApiClient({required this.appBaseUrl}) {
    baseUrl = appBaseUrl;
    timeout = Duration(seconds: 30);
    _mainHeaders = {
      'Content-type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer $token',
    };
  }

  Future<Response> getData(String uri) async {
    try {
      Response response = await get(uri);
      return response;
    } catch (e) {
      return Response(statusCode: 1, statusText: e.toString());
    }
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:food_delivery/controllers/popular_product_controller.dart';
import 'package:food_delivery/pages/food/popular_food_detail.dart';
import 'package:food_delivery/pages/food/recomended_food_detail.dart';
import 'package:food_delivery/pages/home/main_food_page.dart';
import 'package:food_delivery/data/repository/popular_product_repo.dart';

import 'package:get/get.dart';
import 'helper/depencies.dart' as dep;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dep.init;

  // Initialize the PopularProductController

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Get.find<PopularProductController>().getPopularProductList();

    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: RecomencedFoodDetail(),
    );
  }
}

错误信息

════════ Exception caught by widgets library ═══════════════════════════════════
The following message was thrown building MyApp(dirty):
"PopularProductController" not found. You need to call "Get.put(PopularProductController())" or "Get.lazyPut(()=>PopularProductController())"

解决方案

1. 理解Get.lazyPut的延迟特性

Get.lazyPut是延迟初始化,只有当第一次调用Get.find()时才会创建实例。但你在MyApp的build方法中直接调用Get.find(),此时GetMaterialApp还未完成初始化,GetX的依赖容器还未准备好,导致找不到控制器实例。

2. 调整接口调用时机

方式一:在页面的initState中调用

将接口调用移到首页的initState生命周期中,确保GetMaterialApp已经初始化:

class MainFoodPage extends StatefulWidget {
  const MainFoodPage({Key? key}) : super(key: key);

  @override
  State<MainFoodPage> createState() => _MainFoodPageState();
}

class _MainFoodPageState extends State<MainFoodPage> {
  @override
  void initState() {
    super.initState();
    // 此时GetMaterialApp已初始化,可正常获取控制器
    Get.find<PopularProductController>().getPopularProductList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 页面内容
    );
  }
}

同时修改main.dart的home为MainFoodPage():

return GetMaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: const MainFoodPage(),
);

方式二:利用控制器的onInit生命周期

在PopularProductController中重写onInit方法,自动触发接口调用,控制器实例化时会自动执行:

class PopularProductController extends GetxController {
  final PopularProductRepo popularProductRepo;

  PopularProductController({required this.popularProductRepo});

  List<dynamic> _popularProductList = [];
  List<dynamic> get popularProductList => _popularProductList;

  @override
  void onInit() {
    // 控制器初始化时自动调用接口
    getPopularProductList();
    super.onInit();
  }

  Future<void> getPopularProductList() async {
    Response response = await popularProductRepo.getPopularProductList();
    if (response.statusCode == 200) {
      _popularProductList = [];
      _popularProductList.addAll(Product.fromJson(response.body).products);
      update();
    } else {
      // 替换return null,用提示反馈错误
      Get.snackbar("请求失败", "无法获取热门商品数据");
    }
  }
}

3. 修复API URL不一致问题

PopularProductRepo中使用了完整HTTP URL,但ApiClient的baseUrl是HTTPS,协议不一致会导致请求失败,改为仅传路径:

Future<Response> getPopularProductList() async {
  return await apiClient.getData('/api/v1/products/popular');
}

4. 修复ApiClient的token未初始化问题

ApiClient中的token是late变量,初始化时未赋值会导致空指针,添加默认值:

ApiClient({required this.appBaseUrl}) {
  baseUrl = appBaseUrl;
  timeout = Duration(seconds: 30);
  token = ""; // 先设空,后续可通过方法更新
  _mainHeaders = {
    'Content-type': 'application/json; charset=UTF-8',
    'Authorization': 'Bearer $token',
  };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:18:12