You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter项目中humanReadableAddress填充TextField报错问题

问题分析

你遇到的红黄色错误界面是空指针异常导致的:在SearchDestinationPage的build方法中,你使用!强制解包pickUpLocation,但当页面加载时,pickUpLocation可能还未被初始化(比如地理编码请求尚未完成、页面跳转时数据未同步),此时强制解包会触发崩溃。

虽然日志中humanReadableAddress输出正常,但这只代表地理编码请求完成时的值,不代表页面加载时pickUpLocation已经被赋值。


解决方案

方案1:使用Consumer监听状态变化(推荐)

通过Consumer监听AppInfo的变化,仅当pickUpLocation更新时才设置文本框内容,同时避免强制解包:

修改SearchDestinationPage的build方法:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      child: Consumer<AppInfo>(
        builder: (context, appInfo, child) {
          // 安全获取地址,空值时用空字符串兜底
          String userAddress = appInfo.pickUpLocation?.humanReadableAddress ?? "";
          pickUpTextEditingController.text = userAddress;
          
          return Column(
            children: [
              // 保留原有的Card、文本框等组件代码
              Card(
                elevation: 10,
                child: Container(
                  // ... 原代码不变
                ),
              ),
              // ... 原代码不变
            ],
          );
        },
      ),
    ),
  );
}

方案2:在initState中初始化并监听状态

如果不想使用Consumer,可以在页面初始化时获取一次地址,并监听AppInfo的更新:

@override
void initState() {
  super.initState();
  final appInfo = Provider.of<AppInfo>(context, listen: false);
  
  // 初始化时获取地址
  String initialAddress = appInfo.pickUpLocation?.humanReadableAddress ?? "";
  pickUpTextEditingController.text = initialAddress;
  
  // 监听AppInfo变化,实时更新地址
  appInfo.addListener(() {
    String updatedAddress = appInfo.pickUpLocation?.humanReadableAddress ?? "";
    if (pickUpTextEditingController.text != updatedAddress) {
      pickUpTextEditingController.text = updatedAddress;
    }
  });
}

@override
Widget build(BuildContext context) {
  // 移除原build方法中设置控制器的代码,其余代码保留
  return Scaffold(
    body: SingleChildScrollView(
      child: Column(
        // ... 原代码不变
      ),
    ),
  );
}

额外优化:确保pickUpLocation始终被初始化

修改common_methods.dart中的地理编码方法,即使API请求失败,也初始化pickUpLocation,避免空值:

static Future<String> convertGeoGraphicCoOrdinatesIntoHumanReadableAddress(
    Position position, BuildContext context) async {
  String humanReadableAddress = "";
  String apiGeoCodingUrl =
      "https://maps.googleapis.com/maps/api/geocode/json?latlng=${position.latitude},${position.longitude}&key=$googleMapKey";

  var responseFromAPI = await sendRequestToAPI(apiGeoCodingUrl);

  if (responseFromAPI != "error") {
    humanReadableAddress = responseFromAPI["results"][0]["formatted_address"];
    print("humanReadableAddress = " + humanReadableAddress);
  } else {
    // API请求失败时设置提示文本
    humanReadableAddress = "无法获取当前地址";
  }

  AddressModel model = AddressModel();
  model.humanReadableAddress = humanReadableAddress;
  model.longitudePosition = position.longitude;
  model.latitudePosition = position.latitude;

  Provider.of<AppInfo>(context, listen: false).updatePickUpLocation(model);

  return humanReadableAddress;
}

内容的提问来源于stack exchange,提问作者Abhijit Malakar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 10:25:55