为何在 GetBinding 中使用 Get.create() 导致 Controller 不断重复创建?

在Getbinding中使用Get.create()注入依赖时,会一直不停地创建Controller,(使用断点可以发现一直在执行OnReady和OnInit)

Get.toNamed(Routes.MUSICLIST, arguments: arguments, preventDuplicates: false);
import 'package:get/get.dart';

import '../controllers/musiclist_controller.dart';

class MusiclistBinding extends Bindings {
  @override
  void dependencies() {
    Get.create<MusiclistController>(() => MusiclistController());
  }
}

尝试使用Get.put或Get.lazyput注入依赖就没有问题,但我需要打开多个相同的页面

阅读 1.3k
avatarAI BotBETA

在 GetX 框架中,Get.create() 方法的行为是每次请求时都会创建一个新的实例。这是因为它主要用于那些需要每次访问时都是全新实例的场景。然而,在你的场景中,你似乎想要在同一页面或路由的多个实例之间共享同一个 MusiclistController 实例,这通常是通过使用 Get.put()Get.lazyPut() 来实现的。

为什么 Get.create() 导致不断重复创建?

当你使用 Get.toNamed() 导航到相同的路由时,如果 preventDuplicates 设置为 false(如你所做),并且你使用 Get.create() 来创建控制器,那么每次导航到该路由时,都会通过 Get.create() 调用创建一个新的 MusiclistController 实例。这是因为 Get.create() 设计的初衷就是每次调用时都生成一个新的实例。

解决方案

如果你需要确保相同的路由或页面在多次导航时共享同一个控制器实例,你应该使用 Get.put()Get.lazyPut()。这两个方法之间的主要区别在于初始化时机:

  • Get.put():在调用时立即初始化控制器。
  • Get.lazyPut():控制器在第一次被请求时初始化,之后的请求将返回相同的实例。

对于你的场景,使用 Get.put()Get.lazyPut() 是更合适的选择,因为你可以确保无论用户如何导航,他们都将与同一个 MusiclistController 实例交互。

示例

MusiclistBinding 中使用 Get.put()Get.lazyPut()

import 'package:get/get.dart';

import '../controllers/musiclist_controller.dart';

class MusiclistBinding extends Bindings {
  @override
  void dependencies() {
    // 使用 Get.put() 或 Get.lazyPut() 替换 Get.create()
    Get.put<MusiclistController>(MusiclistController());
    // 或者
    // Get.lazyPut<MusiclistController>(() => MusiclistController());
  }
}

确保你的路由配置或页面初始化逻辑正确地引用了这些绑定,以便在需要时注入控制器。

这样修改后,无论用户如何导航到 Routes.MUSICLIST,他们都将与同一个 MusiclistController 实例进行交互,避免了不必要的重复创建和可能的性能问题。

2 个回答

这个文档有说明:

 /// Creates a new Class Instance [S] from the builder callback[S].
  /// Every time `find<S>()` is used, it calls the builder method to generate
  /// a new Instance [S].
  /// It also registers each `instance.onClose()` with the current
  /// Route `GetConfig.currentRoute` to keep the lifecycle active.
  /// Is important to know that the instances created are only stored per Route.
  /// So, if you call `Get.delete<T>()` the "instance factory" used in this
  /// method (`Get.create<T>()`) will be removed, but NOT the instances
  /// already created by it.
  /// Uses `tag` as the other methods.
  ///
  /// Example:
  ///
  /// ```create(() => Repl());
  /// Repl a = find();
  /// Repl b = find();
  /// print(a==b); (false)```
  void create<S>(InstanceBuilderCallback<S> builder,
          {String? tag, bool permanent = true}) =>
      GetInstance().create<S>(builder, tag: tag, permanent: permanent);

Get.create每次都会创建新的

使用Get.lazyPut 结合 Get.find 来用

新手上路,请多包涵

原因是使用Get.create()GetBinding中注入依赖时,每次跳转到相同的页面时,都会创建一个新的Controller实例

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏