Flutter GetX 重新初始化 GetX 控制器 重置 GetX 控制器,重置 GetX 控制器值

Flutter GetX Re-Initialise GetX Controller Reset GetX Controller, Reset GetX Controller Values

我正在自学 Flutter GetX,但坚持了一个观点。其实我想知道为什么每当我再次访问 page/dialog 时,GetX Controlled 的 onInit 方法都没有调用。

假设我有一个简单的 TextField 对话框,一个 Listview,TextField 用于搜索列表视图。当用户在文本字段中输入任何过滤键时,列表视图将被过滤。

这是示例对话框:

import 'package:flutter/material.dart';
import 'package:flutter_base_sample/util/apptheme/colors/app_colors.dart';
import 'package:flutter_base_sample/util/apptheme/styles/text_styles_util.dart';
import 'package:flutter_base_sample/util/commons/app_util.dart';
import 'package:flutter_base_sample/util/widgets/alert/controllers/country_finder_alert_controller.dart';
import 'package:flutter_base_sample/util/widgets/marquee/marquee_widget.dart';
import 'package:flutter_base_sample/util/widgets/textfields/app_text_field.dart';
import 'package:get/get.dart';

class SampleDialogWidget extends StatelessWidget {
  final CountryFinderAlertController controller = Get.put(CountryFinderAlertController(),permanent: true);

  @override
  Widget build(BuildContext context) {
    return Dialog(
      insetPadding: AppUtil.dialogPadding(context),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(20),
      ),
      elevation: 0.0,
      backgroundColor: Colors.white,
      child: dialogContent(context),
    );
  }

  Widget dialogContent(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.max,
      children: [
        Text(
          "Hello Heading",
          style: TextStyleUtil.quickSandBold(context, fontSize: 16, color: Colors.blue),
          textAlign: TextAlign.center,
        ),
        SizedBox(
          height: 20,
        ),
        Expanded(
          child: SingleChildScrollView(
            child: Container(
              height: AppUtil.deviceHeight(context),
              padding: EdgeInsetsDirectional.all(20),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text("Hello Text1"),
                  SizedBox(
                    height: 10,
                  ),
                  getSearchField(context),
                  SizedBox(
                    height: 5,
                  ),
                  Expanded(
                    child: Obx(()=> getFavoritesListView(context)),
                  )
                ],
              ),
            ),
          ),
        ),
        SizedBox(
          height: 20,
        ),
        Container(
          margin: EdgeInsetsDirectional.only(start: 20,end: 20),
          child: ElevatedButton(
            onPressed: () {},
            style: ButtonStyle(
              overlayColor: MaterialStateProperty.all<Color>(Colors.red),
              // splashFactory: NoSplash.splashFactory,
              elevation: MaterialStateProperty.all(0.5),
              backgroundColor: MaterialStateProperty.resolveWith<Color>(
                (Set<MaterialState> states) {
                  if (states.contains(MaterialState.pressed)) {
                    return AppColors.instance.black.withOpacity(0.1);
                  } else {
                    return Colors.blue; // Use the component's default.
                  }
                },
              ),
            ),
            child: Text(
              "Hello Footer",
              style: TextStyleUtil.quickSandBold(context, fontSize: 16, color: Colors.yellow),
              textAlign: TextAlign.center,
            ),
          ),
        )
      ],
    );
  }

  Widget getFavoritesListView(BuildContext context) {
    if (controller.favoritesList.length > 0) {
      return ListView.separated(
        shrinkWrap: true,
        itemCount: controller.favoritesList.length,
        itemBuilder: (BuildContext context, int index) => _topupFavoriteContent(context, index),
        separatorBuilder: (context, index) {
          return Divider(
            indent: 15,
            endIndent: 15,
          );
        },
      );
    } else {
      return Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              "No Data Found!",
              textAlign: TextAlign.center,
            ),
            SizedBox(
              height: 20,
            ),
          ],
        ),
      );
    }
  }

  Widget _topupFavoriteContent(BuildContext context, int index) {
    final item = controller.favoritesList[index];
    return InkWell(
        onTap: () {
          Get.back(result:item);
          // AppUtil.pop(context: context, valueToReturn: item);
        },
        child: getChildItems(context, index));
  }

  Widget getChildItems(BuildContext context, int index) {
    return Directionality(textDirection: TextDirection.ltr, child: getContactNumberAndNameHolder(context, index));
  }

  Widget getContactNumberAndNameHolder(BuildContext context, int index) {
    final item = controller.favoritesList[index];
    return Container(
      padding: EdgeInsetsDirectional.only(start: 20, end: 20, top: 20, bottom: 10),
      child: Column(
        children: [
          Row(
            // crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Flexible(
                child: Align(
                  alignment: AlignmentDirectional.centerStart,
                  child: Text(
                    item.name ?? "",
                    style: TextStyleUtil.quickSandBold(context, fontSize: 15, color: AppColors.instance.black),
                  ),
                ),
              ),
              SizedBox(
                width: 5,
              ),
              Container(),
              Align(
                alignment: AlignmentDirectional.centerEnd,
                child: MarqueeWidget(
                  child: Text(
                    item.dialCode ?? "",
                    style: TextStyleUtil.quickSandBold(context, fontSize: 15, color: Colors.blue),
                  ),
                ),
              ),
            ],
          )
        ],
      ),
    );
  }

  Widget getSearchField(
    BuildContext context,
  ) {
    return Container(
        margin: EdgeInsetsDirectional.only(start: 20, end: 20, top: 20),
        child: Row(
          children: [
            Expanded(
              child: AppTextField(
                onChanged: (String text) {
                  controller.performSearchOnForFavoriteContact(text);
                },
                isPasswordField: false,
                keyboardType: TextInputType.text,
                suffixIconClickCallBack: () {},
              ),
            )
          ],
        ));
  }
}

这是 GetX 控制器:

class CountryFinderAlertController extends GetxController {
  TextEditingController countrySearchFieldEditController = TextEditingController();
  RxList<CountryHelperModel> favoritesList;
  RxList<CountryHelperModel> originalList;

  @override
  void onInit() {
    super.onInit();
    debugPrint("Hello222");
    favoritesList = <CountryHelperModel>[].obs;
    originalList = <CountryHelperModel>[].obs;
  }

  @override
  void onReady() {
    super.onReady();
    debugPrint("Hello111");
    originalList.addAll(JSONHelperUtil.getCountries());
    addAllCountries();
  }

  @override
  void dispose() {
    super.dispose();
    countrySearchFieldEditController.dispose();
  }

  @override
  void onClose() {
    super.onClose();
  }

  void performSearchOnForFavoriteContact(String filterKey) {
    if (filterKey != null && filterKey.isNotEmpty) {
      List<CountryHelperModel> filteredFavoritesList = [];

      debugPrint("filterKey" + filterKey);
      originalList.forEach((element) {
        if (element.name.toLowerCase().contains(filterKey.toLowerCase()) ||
            element.countryCode.toLowerCase().contains(filterKey.toLowerCase()) ||
            element.dialCode.toLowerCase().contains(filterKey.toLowerCase())) {
          filteredFavoritesList.add(element);
        }
      });

      if (filteredFavoritesList.isNotEmpty) {
        favoritesList.clear();
        favoritesList.addAll(filteredFavoritesList);
      } else {
        favoritesList.clear();
      }
    } else {
      //reset the list
      addAllCountries();
    }
  }

  void addAllCountries() {
    favoritesList.clear();
    favoritesList.addAll(originalList);
  }
}

所以我想要的是每次打开此对话框时加载新数据。现在,如果用户搜索任何国家并关闭对话框,然后如果重新打开它,用户将看到较早的搜索结果。

简单来说,GetX 控制器如何 Reset/Destroyed 或重新初始化 !

提前致谢

我相信这是因为 ,permanent: true
尝试将其排除在外。

释放你的资源总是在释放超级资源之后。所以改变以下

@override
  void dispose() {
    super.dispose();
    countrySearchFieldEditController.dispose();
  }

@override
  void dispose() {
    countrySearchFieldEditController.dispose();
    super.dispose();
  }

如果还是不行,请附上绑定文件代码。

控制器不会被释放:

class SampleDialogWidget extends StatelessWidget {
  final CountryFinderAlertController controller = Get.put(CountryFinderAlertController(),permanent: true);

  @override
  Widget build(BuildContext context) {
    return Dialog(

实例化和注册 (Get.put(...)) 不应作为字段完成。

否则,控制器的注册是附加到LandingScreen,而不是MainScreen。并且 Controller 只会在 LandingScreen 被处置时被处置。由于这是上面代码中的主窗口小部件,因此仅在应用程序退出时才会进行处置。

修复:将 Get.put 移动到 build() 方法。

class SampleDialogWidget extends StatelessWidget {
      
      @override
      Widget build(BuildContext context) {
      final CountryFinderAlertController controller = Get.put(CountryFinderAlertController());
        return Dialog(

所以我对这个问题的回答是 Flutter pub GetX 确实提供了一种删除任何初始化控制器的方法。假设我们只有一个控制器 需要在其 onInit() 方法 中调用 API,每次用户 将登陆该特定视图控制器假设!

所以这个问题的解决方案就是调用:

Get.delete<YourControllerName>();

何时调用 重要对我来说 干净的方式 做到这一点,当我转到一个新页面时,我将一个值注册到 return/result 回调:

Get.to(()=>YourWidgetView());

Get.to(()=>YourWidgetView()).then((value) => Get.delete<YourControllerName>());

因此,每当用户将离开您的小部件视图将删除受人尊敬的控制器。这样,当用户再次同一个小部件视图时,控制器将re-initialised 并且所有控制器 值将被重置

如果有人有任何更好的解决方案可以与开发社区分享。 谢谢

别人说初始化controller,其实有时候还有其他的方法。我建议使用 GetWidget 而不是 StatelessWidget

class SampleDialogWidget extends GetWidget<CountryFinderAlertController> {...}

和'your_any_screen_bindings.dart'文件看起来像

class YourAnyScreenBindings implements Bindings {
  @override
  void dependencies() {
    Get.put(YourAnyScreenCtrl());
    Get.create(() => CountryFinderAlertController());
  }
}

和 'your_routes.dart' 文件将...

List<GetPage<dynamic>> getPages = [
  GetPage(
    name: '/your_any_screen',
    page: () => YourAnyScreen(),
    binding: YourAnyScreenBindings(),
  ),
]

现在您的对话框小部件每次都会与一个新控制器配对。

考虑到这是对话框,没有必要使用 Get.put() 方法注入控制器。而是尝试这种方法,每次我们调用 SimpleDialogWidget 时都使用这种方法,它的控制器将在调用 Get.back() 时创建和处理。

第 1 步:用 GetView<CountryFinderAlertController>

扩展您的 SimpleDialogWidget
class SampleDialogWidget extends GetView<CountryFinderAlertController> {...}

第 2 步:将您的实际小部件包装在 Getx 中

class SampleDialogWidget extends GetView<CountryFinderAlertController> {
 

  @override
  Widget build(BuildContext context) {
    return GetX<CountryFinderAlertController>(      //Here it is 
         init : CountryFinderAlertController(),     // like this
         builder: (controller) => Dialog(
      insetPadding: AppUtil.dialogPadding(context),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(20),
      ),
      elevation: 0.0,
      backgroundColor: Colors.white,
      child: dialogContent(controller, context), // Also, pass the controller to dialogContent function
    );
  
    );
   }
}

这将解决您的问题。