【问题标题】:Flutter GetX state management does not workFlutter GetX 状态管理不起作用
【发布时间】:2021-11-10 06:17:34
【问题描述】:

我面临的问题是 ui 文本没有得到更新。我想要的数据,在本例中为 placeName,已在 DEBUG 控制台上成功打印,但它不会更改文本小部件 UI。我认为在 Getx 中的简单语句管理中,它会在方法中使用 update() 更新变量。我遇到过类似的情况,之前我无法弄清楚,所以我不得不使用 statefuleWidget 来解决它。但是,这次我想继续使用 Getx。

enter image description here

有人可以帮帮我吗?

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); // previous

// current
 Address? address = await UberRepository.to.searchCoordinateAddress(position);
 pickUpLocation(address);
 isLoading(true);
}


// previous
/*
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?> // previous
  // current
  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; // current

      // HomeController().updatePickUpLocationAddress(userPickUpAddress); // previous


    }
    // return placeAddress; // previous
  }
}
// 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;
                // when map created and map is set correctly, call current location
                controller.setBottomPaddingOfMap();
                controller.locatePosition(); 
              },
            ),
...
...
Expanded(
    child: Obx(() => 
                  Column(
              crossAxisAlignment: CrossAxisAlignment.start,
                 children: [
                    // TODO: UI update...
                    !controller.isLoading.value
                          ? CircularProgressIndicator()
                          : Text(
                             controller.pickUpLocation.value != null
                          ? controller.pickUpLocation.value.placeName!
                               : "Add Home",
                               maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                            softWrap: false,
                              ),
                              SizedBox(height: 4.0),
                              Text(
                                "Your living home address",
                                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,
  });
}

【问题讨论】:

    标签: flutter flutter-getx


    【解决方案1】:

    您可以使用Obx 来完成。在你的控制器类中做这样的事情

    class HomeController extends GetxController {
    
         Address get pickupLocation => _pickupLocation.value;
    
      set pickupLocation(Address value) {
        _pickupLocation.value = value;
      }
    
      Rx<Address> pickUpLocation= Rx<Address>(Address());
      ...
      ...
      ...
    
    
      void updatePickUpLocationAddress(Address? pickUpAddress) {
        pickUpLocation = pickUpAddress;
        print("Here? ${pickUpLocation!.placeName!}"); // printed correctly as I intended
      }
    }
    

    现在在你的 UI 类中使用 Obx 而不是 GetBuilder 像这样

    // home.dart
    class Home extends GetView<HomeController> {
      const Home({
        Key? key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
    ...
    ...
    ...
    ...
                Obx(() => controller.pickupLocation.placeName != null
                            ? Text(controller.pickupLocation.placeName)
                            : Text('Add home')),
    ...
    

    【讨论】:

    • 我按照你的代码,有空检查错误,我把 Obx(() => ) 移到父Widget,错误消失了,但是placeName数据是'',空字符串.我认为它不适用于ui...我该怎么办?
    • 我可以在 HomeController 上打印我想要的数据,但是 ui 端没有更新并且它显示 ("") 空字符串。所以,我猜 Home 的 build Method,比 HomeController 更早返回 Widget,因此数据不适用于 ui。你对此有什么想法吗?
    • 调用 onInit() 中的 api 方法,并添加一个标志来跟踪您是否已经得到响应。当你加载状态时,你可以显示一个进度对话框,当pickupLocation用api值更新时,更新状态。
    • 我还在为这件事苦苦挣扎...我在Controller上添加了isLoading Rxbool变量,当它为真时我编码,显示placeName,我还检查了打印pickUpLocation.value.placeName是否更新较早比 isLoading 变为真。但是,UI 端的 controller.pickUpLocation.value.placeName 为空。我该怎么办?好郁闷
    • 控制器中的值是否更新?
    【解决方案2】:

    我认为你必须在你的小部件中调用pickUpLocation.refresh()。以下是来自 getx 开发页面 https://pub.dev/packages/get 的示例中的相关部分:

    // `Rx` don't have any clue when you change something inside user.
    // So, for custom classes, we need to manually "notify" the change.
    user.refresh();
    

    【讨论】:

    • 我在 updatePickUpLocationAddress 函数中添加了 pickUpLocation.refresh(),它不起作用,我使用了更新方法,如下所示,```pickUpLocation.update((value) { value!.placeName = pickUpAddress.placeName; }); ``` ui 仍然没有更新...我只能看到 placeName 打印正确...但不是在 UI 端。
    猜你喜欢
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 2021-12-10
    • 2021-10-07
    • 2022-01-21
    • 2021-11-08
    • 2021-12-22
    相关资源
    最近更新 更多