Flutter GetX状态管理失效:placeName打印正常但Text组件UI不更新如何解决
GetX 状态管理UI文本无法更新问题解决记录
问题描述
UI文本无法更新,需要的placeName数据可以在调试控制台正常打印,但无法刷新Text组件的显示内容。原本以为GetX简易状态管理中,在方法内调用update()就能更新变量。之前遇到过同样的问题没有找到原因,只能用StatefulWidget解决,本次希望通过GetX实现对应功能。
点击查看动图
2021-11-10 更新
更新代码后问题仍然存在
2021-11-18 问题解决
通过修改searchCoordinateAddress函数的返回类型,将返回值直接赋值给需要更新的pickUpLocation变量解决了该问题。
相关代码
home_controller.dart
class HomeController extends GetxController { ... Rx<Address> pickUpLocation = Address().obs; RxBool isLoading = false.obs; ... void locatePosition() async { ... ... // String? address = await UberRepository.to.searchCoordinateAddress(position); // 旧代码 // 新代码 Address? address = await UberRepository.to.searchCoordinateAddress(position); pickUpLocation(address); isLoading(true); } // 旧代码 /* void updatePickUpLocationAddress(Address pickUpAddress) { print("pickUpAddress.placeName: ${pickUpAddress.placeName}"); pickUpLocation(pickUpAddress); print("pickUpLocation.value.placeName: ${pickUpLocation.value.placeName}"); } } */
uber_repository.dart
class UberRepository extends GetConnect { static UberRepository get to => Get.find(); @override void onInit() { httpClient.baseUrl = 'https://maps.googleapis.com/'; super.onInit(); } // Future<String?> // 旧代码 // 新代码 Future<Address?> searchCoordinateAddress(Position position) async { String placeAddress = ""; String url = 'maps/api/geocode/json?latlng=${position.latitude},${position.longitude}&key=$mapKey'; final response = await get(url); if (response.status.hasError) { Future.error(response.statusText!); } else { placeAddress = response.body["results"][0]["formatted_address"]; Address userPickUpAddress = Address(); userPickUpAddress.latitude = position.latitude; userPickUpAddress.longitude = position.longitude; userPickUpAddress.placeName = placeAddress; return userPickUpAddress; // 新代码 // HomeController().updatePickUpLocationAddress(userPickUpAddress); // 旧代码 } // return placeAddress; // 旧代码 } }
home.dart
class Home extends GetView<HomeController> { const Home({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( ... body: Stack( children: [ GoogleMap( padding: EdgeInsets.only( bottom: controller.bottomPaddingOfMap.value, ), mapType: MapType.normal, myLocationButtonEnabled: true, initialCameraPosition: controller.kGooglePlex, myLocationEnabled: true, zoomGesturesEnabled: true, zoomControlsEnabled: true, onMapCreated: (GoogleMapController googleMapController) { controller.controllerGoogleMap.complete(googleMapController); controller.newGoogleMapController = googleMapController; // 地图创建完成并正确加载后,调用方法获取当前位置 controller.setBottomPaddingOfMap(); controller.locatePosition(); }, ), ... ... Expanded( child: Obx(() => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // TODO: UI更新逻辑 !controller.isLoading.value ? CircularProgressIndicator() : Text( controller.pickUpLocation.value != null ? controller.pickUpLocation.value.placeName! : "添加家庭地址", maxLines: 2, overflow: TextOverflow.ellipsis, softWrap: false, ), SizedBox(height: 4.0), Text( "你的家庭居住地址", style: TextStyle( color: Colors.black54, fontSize: 12.0, ), ), ], ), ), ), ...
address.dart
class Address { String? placeFormattedAddress; String? placeName; String? placeId; double? latitude; double? longitude; Address({ this.placeFormattedAddress, this.placeName, this.placeId, this.latitude, this.longitude, }); }
根因说明
旧代码在UberRepository中调用HomeController().updatePickUpLocationAddress()时,重新创建了一个HomeController实例,这个实例不在GetX的依赖注入容器中,和页面绑定的Controller不是同一个对象,所以修改该新实例的响应式变量无法触发UI刷新。修改后改为由页面绑定的Controller直接接收异步方法返回的Address对象,再赋值给自身的响应式变量,即可正常触发Obx的UI刷新逻辑。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

