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
);
);
}
}
这将解决您的问题。
我正在自学 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
);
);
}
}
这将解决您的问题。