问题一:在Controller里面注入依赖
// 创建了 PostApi
class PostApi extends GetConnect {
@override
void onInit() {
httpClient.baseUrl = "https://jsonplaceholder.typicode.com";
super.onInit();
}
Future<Response> getPosts() => get("/posts");
}
// 创建 Controller
class PostController extends GetxController with StateMixin<List<dynamic>> {
// final PostApi api = Get.find<PostApi>();
final PostApi api = PostApi();
void fetchPosts() async {
// 发送请求,但是response没有返回值
final response = await api.getPosts();
}
}
上面这么写的问题:GetX 可能会提前实例化 PostApi
当在 Controller 里写
final PostApi api = Get.put(PostApi());
,每次 Controller 被创建时,PostApi 也会被创建或注入。这样 PostApi 的生命周期就和 Controller 绑定在一起——Controller 什么时候创建,PostApi 就什么时候创建。App 启动时,Flutter 框架、GetX 容器、网络环境等都需要初始化。如果你在 Controller 构造时就 new 或注入 PostApi,可能此时 App 还没完成所有初始化(比如 runApp 还没执行,GetX 容器还没准备好),导致 PostApi 的 onInit、baseUrl、httpClient 等配置还没生效。
这样 PostApi 虽然被创建了,但它的配置和依赖可能还没准备好,网络请求就会异常(比如 baseUrl 没有设置,GetConnect 没有注册到容器,导致请求路径错误或请求发不出去)。
问题二:依赖的顺序问题
Future<void> main() async {
// Get.put(CountController());
final PostController controller = Get.put(PostController());
final PostApi api = Get.put(PostApi()); runApp(MyApp());
}
PostController
里面用到了PostApi
我上面这么写,会先创建PostController
再创建PostApi
但是在PostController
里面有这么一段代码
// 成员变量
final PostApi api = Get.find<PostApi>();
那么我在创建PostController
的时候,会去IOC容器里面找PostApi
,可是这个时候PostApi
还没有被创建也没有被注册到容器汇总,就会发生报错。
正确顺序应该是先 put PostApi
,再 put PostController
:
final PostApi api = Get.put(PostApi());
final PostController controller = Get.put(PostController());
正确做法使用Binding
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.put(PostApi()); // PostApi 先注册
Get.put(PostController()); // PostController 再注册(内部安全依赖 PostApi)
}
}
依赖顺序可控
- 你在
dependencies()
里按顺序写,GetX 就按顺序执行。 - 不会出现
AController
先执行onInit()
时找不到BController
的情况。
和路由强绑定
- 每个页面进入时,GetX 自动执行
Binding
,不需要你在main()
或某个地方手动管理。 - 依赖和页面解耦,项目更清晰。
生命周期安全
- 页面关闭时,对应的 Controller 会自动释放(除非设置
permanent: true
或fenix: true
)。
团队协作友好
- 只要看某个页面的
Binding
,就能知道它依赖了哪些控制器。 - 避免了“到处
Get.put()
/Get.find()
导致乱”的问题。
使用LazyPut
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.LazyPut(PostController());
Get.LazyPut(PostApi());
}
}
对于一些依赖比较复杂的情况,我们可以使用懒加载。它的好处是,在Get.LazyPut
的时候不会马上创建实例,需要用到的时候(Get.find
)才会去创建。这样创建的顺序自然就是依赖创建的顺序,自然而然不需要关注依赖的注入顺序。
另外一点,不会一次性把所有依赖都初始化,减少内存占用和启动耗时,性能也得到了优化。