首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >颤振GetX Get.back()或navigator.pop()从内存中删除控制器,并且无法重新创建它

颤振GetX Get.back()或navigator.pop()从内存中删除控制器,并且无法重新创建它
EN

Stack Overflow用户
提问于 2021-02-10 14:12:21
回答 5查看 37.9K关注 0票数 12

我有两页:GetxControllers. HomePageDetailsPage

HomePage

代码语言:javascript
运行
复制
class HomePage extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('HomePage')),
      body: Container(
        child: Obx(
          () => ListView.builder(
            itemCount: controller.task.length,
            itemBuilder: (context, index) {
              return ListTile(
                leading: Text('${index + 1}'),
                title: Text(controller.task[index]["name"]),
                onTap: () {
                  Get.to(
                    DetailsPage(),
                    arguments: controller.task[index]["name"],
                  );
                },
              );
            },
          ),
        ),
      ),
    );
  }
}

HomeController

代码语言:javascript
运行
复制
class HomeController extends GetxController {
  final TaskRepository repository;
  HomeController({@required this.repository}) : assert(repository != null);

  final _task = [].obs;
  set task(value) => this._task.assignAll(value);
  get task => this._task;

  onInit() {
    super.onInit();
    getAllTask();
  }

  getAllTask() {
    repository.getAll().then((value) => task = value);
  }
}

如您所见,HomeController依赖于一个TaskRepository,这是一个模拟回购。

和我的DetailsPage

代码语言:javascript
运行
复制
class DetailsPage extends GetView<DetailsController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          GestureDetector(
            onTap: () {
              Get.back();
            },
            child: Row(
              children: [
                Icon(Icons.arrow_back),
                Text('Go Back'),
              ],
            ),
          ),
          Expanded(
            child: Center(
              child: Obx(
                () => Text(controller.taskDetail.value),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

DetailsController

代码语言:javascript
运行
复制
class DetailsController extends GetxController {
  final taskDetail = ''.obs;

  @override
  void onInit() {
    super.onInit();
    taskDetail.value = Get.arguments;
  }
}

我创建了一个AppDependencies类来初始化依赖项(控制器、存储库、API客户端等):

代码语言:javascript
运行
复制
class AppDependencies {
  static Future<void> init() async {
    Get.lazyPut(() => HomeController(repository: Get.find()));
    Get.lazyPut(() => DetailsController());
    Get.lazyPut(() => TaskRepository(apiClient: Get.find()));
    Get.lazyPut(() => TaskClient());
  }
}

我正在通过在AppDependencies.init()上调用main()来初始化所有依赖项

代码语言:javascript
运行
复制
void main() async {
  await AppDependencies.init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

HomePage

DetailsPage第一次

回到HomePage,然后再去DetailsPage

正如您在第三张图片中所看到的,从DetailsPage返回到HomePage,然后返回DetailsPage,会导致一个异常,即:

代码语言:javascript
运行
复制
"DetailsController" not found. You need to call "Get.put(DetailsController())" or "Get.lazyPut(()=>DetailsController())"

但我已经在main()上这么做了。我也尝试使用Get.put()而不是Get.lazyPut(),但是我发现对于Get.put(),任何其他依赖项的依赖都必须在依赖依赖的依赖项之前注册。例如,HomeController依赖于TaskRepository,因此如果使用Get.put(),则TaskRepository必须位于HomeController之前:

代码语言:javascript
运行
复制
Get.put(TaskRepository());

Get.put(HomeController());

这不是我想要的,因为我不想在手动跟踪之前跟踪什么。我发现,如果有一个后退按钮(几乎每一页都有),就会产生这种情况。

我在这里做错了什么?

EN

回答 5

Stack Overflow用户

发布于 2021-06-09 15:21:19

如果不想使用fenix = true,可以在单击方法中使用类似的内容:

代码语言:javascript
运行
复制
try {
   ///find the controller and 
   ///crush here if it's not initialized
   final authController = Get.find<AuthController>();

   if(authController.initialized)
     Get.toNamed('/auth');
   else {
     Get.lazyPut(() => AuthController());
     Get.toNamed('/auth');
   }

} catch(e) {

   Get.lazyPut(() => AuthController());
   Get.toNamed('/auth');
}

关于内存,重要的是要考虑fenix参数:

如果使用Get.delete()删除实例,构建器()的内部寄存器将保留在内存中以重新创建实例。因此,将来对Get.find()的调用将返回相同的实例。

票数 8
EN

Stack Overflow用户

发布于 2021-03-30 02:45:23

您需要绑定所有控制器和添加到GetMaterialApp.中的

您面临这一问题,因为当您当时使用它时,它会删除或删除控制器,比如:GETX "LoginController“onDelete(),称为

为了防止这个问题,您需要创建InitialBinding.

InitialBinding

代码语言:javascript
运行
复制
class InitialBinding implements Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => LoginController(LoginRepo()), fenix: true);
    Get.lazyPut(() => HomeController(HomeRepo()), fenix: true);
  }
}

的主要方法:

代码语言:javascript
运行
复制
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Get.put(AppController());
    return GetMaterialApp(
      title: StringConst.APP_NAME,
      debugShowCheckedModeBanner: false,
      defaultTransition: Transition.rightToLeft,
      initialBinding: InitialBinding(),
      theme: ThemeData(
        primarySwatch: ColorConst.COLOR,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      initialRoute: RoutersConst.initialRoute,
      getPages: routes(),
    );
  }
}

谢谢

票数 5
EN

Stack Overflow用户

发布于 2021-02-10 15:54:08

带绑定的更新答复:

您可以更好地控制控制器如何和何时使用绑定和智能管理进行初始化。因此,如果每次访问页面时都需要使用onInit来触发,则可以使用绑定来实现。为详细信息页设置专用绑定类。

代码语言:javascript
运行
复制
class DetailsPageBinding extends Bindings {
  @override
  void dependencies() {
    // any controllers you need for this page you can lazy init here without setting fenix to true
  }
}

如果您尚未使用GetMaterialApp而不是MaterialApp,则需要这样做。我建议在页面上抛出static const id = 'details_page';,这样您就不必为路由处理原始字符串了。

GetMaterialApp的一个基本示例如下所示。

代码语言:javascript
运行
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      initialRoute: HomePage.id,
      title: 'Material App',
      getPages: [
        GetPage(name: HomePage.id, page: () => HomePage()),

// adding the new bindings class in the binding field below will link those controllers to the page and fire the dependancies override when you route to the page

        GetPage(name: DetailsPage.id, page: () => DetailsPage(), binding: DetailsPageBinding()),
      ],
    );
  }
}

然后你需要做你的路由

代码语言:javascript
运行
复制
Get.toNamed(DetailsPage.id)

原来的答案:

fenix: true添加到懒惰的init中;检查lazyPut上的文档。

代码语言:javascript
运行
复制
Get.lazyPut(() => HomeController(repository: Get.find()), fenix: true);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66138542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档