在 GetX 包旁边使用 keepalive mixin 是否有任何解决方法?

问题描述

我使用 TabBarView 创建了一个基于滑块的步进表单,它在切换前验证输入。它有效,但是当我回去时,状态已重置。当我尝试收集选项卡末尾的数据时,这种行为导致我看到一个空表单。

我在谷歌上搜索了几个小时,并尝试将当前的 GetView<MyController> 切换到经典的 StatefulWidget with AutomaticKeepAliveMixin,但没有成功,所以我将其还原。

我有点卡住了,我想知道是否还有其他方法可以实现这一点,如果可能的话,GetX 方法。

visual explanation

enter image description here

`

create_account_form_slider.dart

class CreateAccountFormSlider extends GetView<CreateAccountController> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: TabBarView(
        physics: const NeverScrollableScrollPhysics(),controller: controller.tabController,children: [
          _buildEmailForm(),_buildNameForm(),_buildPasswordForm(),],),);
  }

  Widget _buildEmailForm() {
    return Form(
      key: controller.emailFormKey,child: Column(
        children: [
          Spacer(),// Necessary to push the input to the bottom constraint,Align class doesn't work.
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20.0),child: FormInput(
              focusNode: controller.emailFocusNode,margin: EdgeInsets.zero,label: 'create_account_form_email'.tr,hintText: 'janedoe@example.com',textInputAction: TextInputAction.next,keyboardType: TextInputType.emailAddress,validator: controller.emailValidator,onFieldSubmitted: (_) => controller.next(),);
  }

... each form has similar structure (almost identical),so i will not include it here

create_account_controller.dart

class CreateAccountController extends GetxController
    with SingleGetTickerProviderMixin {

  final tabIndex = 0.obs;


  final emailFormKey = GlobalKey<FormState>();
  FormState get emailForm => emailFormKey.currentState;

  final emailFocusNode = FocusNode();
  final email = ''.obs;

  TabController tabController;

  @override
  void onInit() {
    _initTabController();
    super.onInit();
  }

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

  /// Initialize tab controller and add a listener.
  void _initTabController() {
    tabController = TabController(vsync: this,length: 3);
    tabController.addListener(_tabListener);
  }

  /// Listen on tab change and update `tabIndex`
  void _tabListener() => tabIndex(tabController.index);

  /// Dispose tab controller and remove its listener.
  void _disposeTabController() {
    tabController.removeListener(_tabListener);
    tabController.dispose();
  }

  /// Dispose all the focus nodes.
  void _disposeFocusNodes() {
    emailFocusNode.dispose();
  }


  /// Animate to the next slide.
  void _nextSlide() => tabController.animateTo(tabIndex() + 1);

  /// Animate to the next slide or submit if current tab is the last tab.
  void next() {
    if (tabIndex().isEqual(0) && emailForm.validate()) {
      _nextSlide();
      return focusScope.requestFocus(nameFocusNode);
    }
    ...
  }

  /// A function that checks the validity of the given value.
  ///
  /// When the email is empty,show required error message and when the email
  /// is invalid,show the invalid message.
  String emailValidator(String val) {
    if (val.isEmpty) return 'create_account_form_error_email_required'.tr;
    if (!val.isEmail) return 'create_account_form_error_email_invalid'.tr;
    return null;
  }

  /// Submit data to the server.
  void _submit() {
    print('TODO: implement submit');
    print(email());
  }
}

解决方法

我通过保存表单并在我的自定义 initialValue 小部件上添加一个 FormInput 然后将可观察变量放到每个相关的 FormInput 上来实现。无需使用 keepalive mixin。

create_account_controller.dart

  /// Animate to the next slide or submit if current tab is the last tab.
  void next() {
    if (tabIndex().isEqual(0) && emailForm.validate()) {
      // save the form so the value persisted into the .obs variable
      emailForm.save();
      
      // slide to next form
      _nextSlide();

      // TODO: wouldn't it be nice if we use autofocus since we only have one input each form?
      return focusScope.requestFocus(nameFocusNode);
    }

    ...
  }

create_account_form_slider.dart

Obx( // wrap the input inside an Obx to rebuild with the new value
  () => Padding(
    padding: const EdgeInsets.symmetric(horizontal: 20.0),child: FormInput(
      focusNode: controller.emailFocusNode,label: 'create_account_form_email'.tr,hintText: 'janedoe@example.com',textInputAction: TextInputAction.next,keyboardType: TextInputType.emailAddress,validator: controller.emailValidator,onFieldSubmitted: (_) => controller.next(),initialValue: controller.email(),// use initial value to keep current value when user go back from the next slide
      onSaved: controller.email,// persist current value into the .obs variable
    ),),

仅供参考:FormInput 只是一个普通的 TextInput,只有 decoration 被修改。这应该适用于常规颤振 TextInput

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...