如何解决“未经手”的例外:setState()或markneedsbuild()在构建过程中调用?
在这里,我使用OBX显示一个OBS变量,首先没有显示错误,但是当我进行热重新启动时,它显示了此错误。
未经手的异常:setState()或MarkneedSbuild()在构建过程中调用。 这个OBX小部件不能被标记为需要构建,因为该框架已经在构建小部件的过程中。仅当其祖先之一目前正在建造时,才能将小部件标记为需要在构建阶段建造。允许使用此例外,因为该框架在孩子们面前建立了父母小部件,这意味着将始终建造一个肮脏的后代。否则,该框架可能不会在此构建阶段访问此小部件。 setState()或MarkneedSbuild()的小部件是: OBX
class CheckoutScreen extends StatelessWidget {
const CheckoutScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var detailHotelController = Get.put(DetailHotelController());
var homeController = Get.put(HomeController());
var userDataFormController = Get.put(UserDataFormController());
var checkoutController = Get.put(CheckoutController());
var bookingController = Get.put(BookingController());
var authController = Get.put(AuthController());
final orientation = MediaQuery.of(context).orientation;
detailHotelController.getDetailHotel(userDataFormController.hotelId.value);
return Scaffold(
appBar: AppBar(
centerTitle: true,
toolbarHeight: 20.w,
title: Image.asset(
"assets/turu.png",
height: 10.h,
),
elevation: 0,
backgroundColor: Colors.white10,
),
body: Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: SingleChildScrollView(
child: Obx(
() => (detailHotelController.isLoading.value)
? Center(
child: LoadingAnimationWidget.waveDots(
color: const Color(0xffF0B900), size: 50))
: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Tinjau Pemesanan",
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xffF0B900),
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 1.sp,
),
),
Text(
detailHotelController.detailHotel.value.hotel!.name,
style: TextStyle(
fontSize: 13.sp, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 12,
),
Text(
detailHotelController
.detailHotel.value.hotel!.address
.replaceAll("\n", " "),
style: TextStyle(fontSize: 10.sp),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Check-In",
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
Text(
homeController
.checkInController.value.text,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w300))
],
),
SizedBox(
width: 16.w,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Check-Out",
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.bold)),
Text(
homeController
.checkOutController.value.text,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w300))
],
),
],
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
"Detail Pesanan",
style: TextStyle(
fontSize: 12.sp, fontWeight: FontWeight.bold),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Subtotal",
style: TextStyle(fontSize: 12.sp),
),
Text(
RupiahUtils.beRupiah(
userDataFormController.subtotal.value),
style: TextStyle(fontSize: 12.sp))
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
children: [
Expanded(
child: CustomTextField(
label: "Masukkan Kode Promo",
errorText: "",
controller: checkoutController.promoController.value,
isPasswordField: false,
isRequired: false,
)),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: const Color(0xffF0B900)),
onPressed: () => checkoutController.checkPromo(checkoutController.promoController.value.text, userDataFormController.subtotal.value.toString()),
child: checkoutController.isLoading.value ? LoadingAnimationWidget.twoRotatingArc(color: Colors.white, size: 20) : const Text("Terapkan",)),
)
],
),
Visibility(visible: checkoutController.isVisible.value, child: Text(checkoutController.placeholderCheckPromo.value, style: TextStyle(color: checkoutController.textColor.value))),
SizedBox(
width: orientation == Orientation.landscape ? 100.h : 100.w,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
side: const BorderSide(
width: 1.0, color: Color(0xffF0B900))),
onPressed: () {
Get.to(() => const PromoList());
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Lihat Daftar Promo",
style: TextStyle(
color: const Color(0xffF0B900),
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
),
),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Promo Diskon",
style: TextStyle(fontSize: 12.sp),
),
Text(
checkoutController.promoType.value == "Cashback" ? "-Rp 0" : RupiahUtils.beRupiah(checkoutController.totalPromoAmount.value),
style: TextStyle(fontSize: 12.sp),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Cashback",
style: TextStyle(fontSize: 12.sp),
),
Text(
checkoutController.promoType.value == "Cashback" ? RupiahUtils.beRupiah(checkoutController.totalPromoAmount.value) : "-Rp 0",
style: TextStyle(fontSize: 12.sp),
),
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Total",
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold),
),
Text(
RupiahUtils.beRupiah(checkoutController.total.value),
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold),
),
],
),
Padding(
padding:
const EdgeInsets.only(top: 16.0, bottom: 8.0),
child: SizedBox(
width: orientation == Orientation.landscape
? 100.h
: 100.w,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: const Color(0xffF0B900),
),
onPressed: () {
bookingController.postBooking(
context,
authController.userToken.value,
detailHotelController.detailHotel.value.hotel!.id,
homeController.checkInController.value.text,
homeController.checkOutController.value.text,
checkoutController.total.value.toString(),
checkoutController.promoController.value.text,
userDataFormController.detailBooking
);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Proses Booking",
style: TextStyle(
color: Colors.white,
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
),
),
),
),
]),
),
),
),
),
);
}
}
有人可以帮助我确定我的代码有什么问题吗?
Here i am using obx to display an obs variable, at first the error didn't show up, but when i did hot restart, it show this error.
Unhandled Exception: setState() or markNeedsBuild() called during build.
This Obx widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
Obx
class CheckoutScreen extends StatelessWidget {
const CheckoutScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var detailHotelController = Get.put(DetailHotelController());
var homeController = Get.put(HomeController());
var userDataFormController = Get.put(UserDataFormController());
var checkoutController = Get.put(CheckoutController());
var bookingController = Get.put(BookingController());
var authController = Get.put(AuthController());
final orientation = MediaQuery.of(context).orientation;
detailHotelController.getDetailHotel(userDataFormController.hotelId.value);
return Scaffold(
appBar: AppBar(
centerTitle: true,
toolbarHeight: 20.w,
title: Image.asset(
"assets/turu.png",
height: 10.h,
),
elevation: 0,
backgroundColor: Colors.white10,
),
body: Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: SingleChildScrollView(
child: Obx(
() => (detailHotelController.isLoading.value)
? Center(
child: LoadingAnimationWidget.waveDots(
color: const Color(0xffF0B900), size: 50))
: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Tinjau Pemesanan",
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xffF0B900),
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 1.sp,
),
),
Text(
detailHotelController.detailHotel.value.hotel!.name,
style: TextStyle(
fontSize: 13.sp, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 12,
),
Text(
detailHotelController
.detailHotel.value.hotel!.address
.replaceAll("\n", " "),
style: TextStyle(fontSize: 10.sp),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Check-In",
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
Text(
homeController
.checkInController.value.text,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w300))
],
),
SizedBox(
width: 16.w,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Check-Out",
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.bold)),
Text(
homeController
.checkOutController.value.text,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w300))
],
),
],
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
"Detail Pesanan",
style: TextStyle(
fontSize: 12.sp, fontWeight: FontWeight.bold),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Subtotal",
style: TextStyle(fontSize: 12.sp),
),
Text(
RupiahUtils.beRupiah(
userDataFormController.subtotal.value),
style: TextStyle(fontSize: 12.sp))
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
children: [
Expanded(
child: CustomTextField(
label: "Masukkan Kode Promo",
errorText: "",
controller: checkoutController.promoController.value,
isPasswordField: false,
isRequired: false,
)),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: const Color(0xffF0B900)),
onPressed: () => checkoutController.checkPromo(checkoutController.promoController.value.text, userDataFormController.subtotal.value.toString()),
child: checkoutController.isLoading.value ? LoadingAnimationWidget.twoRotatingArc(color: Colors.white, size: 20) : const Text("Terapkan",)),
)
],
),
Visibility(visible: checkoutController.isVisible.value, child: Text(checkoutController.placeholderCheckPromo.value, style: TextStyle(color: checkoutController.textColor.value))),
SizedBox(
width: orientation == Orientation.landscape ? 100.h : 100.w,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white,
side: const BorderSide(
width: 1.0, color: Color(0xffF0B900))),
onPressed: () {
Get.to(() => const PromoList());
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Lihat Daftar Promo",
style: TextStyle(
color: const Color(0xffF0B900),
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
),
),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Promo Diskon",
style: TextStyle(fontSize: 12.sp),
),
Text(
checkoutController.promoType.value == "Cashback" ? "-Rp 0" : RupiahUtils.beRupiah(checkoutController.totalPromoAmount.value),
style: TextStyle(fontSize: 12.sp),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Cashback",
style: TextStyle(fontSize: 12.sp),
),
Text(
checkoutController.promoType.value == "Cashback" ? RupiahUtils.beRupiah(checkoutController.totalPromoAmount.value) : "-Rp 0",
style: TextStyle(fontSize: 12.sp),
),
],
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Divider(
color: Colors.grey,
height: 2,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Total",
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold),
),
Text(
RupiahUtils.beRupiah(checkoutController.total.value),
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold),
),
],
),
Padding(
padding:
const EdgeInsets.only(top: 16.0, bottom: 8.0),
child: SizedBox(
width: orientation == Orientation.landscape
? 100.h
: 100.w,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: const Color(0xffF0B900),
),
onPressed: () {
bookingController.postBooking(
context,
authController.userToken.value,
detailHotelController.detailHotel.value.hotel!.id,
homeController.checkInController.value.text,
homeController.checkOutController.value.text,
checkoutController.total.value.toString(),
checkoutController.promoController.value.text,
userDataFormController.detailBooking
);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Proses Booking",
style: TextStyle(
color: Colors.white,
fontSize: 10.sp,
fontWeight: FontWeight.bold),
),
),
),
),
),
]),
),
),
),
),
);
}
}
Can someone help me to identify what's wrong with my code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
详细信息hotelcontroller.getDetailHotel(userdataformcontroller.hotelid.value);
这条线导致了问题。
您不应从
build
方法调用此方法,而应从getxController的生命周期方法之一调用。oninit()
是一个好地方。有什么问题?
obx
小部件就像statefulwidget
的一部分,就像每次观察可观察的更改时都调用setState()方法一样。但是,当您热加载加热时,上述控制器方法被调用(因为热重新加载调用build
方法,然后也称为上述方法),导致可观察到可观察到的更改,从而在构建中触发重建。detailHotelController.getDetailHotel(userDataFormController.hotelId.value);
This line is causing the problem.
Instead of calling this method from the
build
method, you should call it from one of the lifecycle method of the GetxController.onInit()
is a good place.What's wrong?
The
Obx
widget is like a chunk ofStatefulWidget
which is like calling the setState() method every time the watched observable changes. But when you hot reload, the above controller method is called (because hot reload calls thebuild
method and then the above method also gets called) causing the observable to change thus triggering rebuild in the middle of a build.