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

Flutter修改代码后出现StateError及空感知运算符警告求助

问题修复方案

1. 修复Bad state: Future already completed错误

错误原因:Completer<GoogleMapController> _controller在MapsView类中初始化,热重载时build方法重复执行,onMapCreated会再次调用_controller.complete(controller),但Completer对象只能被完成一次,触发状态错误。

修复方法:在onMapCreated回调中先判断Completer是否已完成,仅在未完成时调用complete:

onMapCreated: (GoogleMapController controller) {
  if (!_controller.isCompleted) {
    _controller.complete(controller);
  }
},

更贴合GetX架构的优化方案:将GoogleMapController的持有逻辑移到MapsController中,避免在View层维护状态变量。示例:
在MapsController中添加:

final mapController = Completer<GoogleMapController>();

View层直接使用controller.mapController替代原_controller,热重载时控制器状态会被正确管理。

2. 修复空感知运算符警告

警告提示:The receiver can't be null, so the null-aware operator '?[' is unnecessary.,对应代码行listCampus?[i].data()。

原因:此前已通过listCampus!断言listCampus不为空,?[]空感知运算符属于冗余写法。

修复方法:将listCampus?[i]改为listCampus[i],同时注意修复ListView.builder中相同的问题:

// 循环中的修复
var detailCampus = listCampus[i].data()! as Map<String, dynamic>;

// ListView.builder中的修复
var detailCampus = listCampus[index].data()! as Map<String, dynamic>;

完整修复后的代码

class MapsView extends GetView<MapsController> {
  MapsView({Key? key}) : super(key: key);

  Completer<GoogleMapController> _controller = Completer();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder<QuerySnapshot<Object?>>(
          stream: controller.getCampus(),
          builder: (context, snap) {
            if (snap.connectionState == ConnectionState.waiting) {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
            if (snap.hasData) {
              var listCampus = snap.data?.docs;
              for (var i = 0; i < listCampus!.length; i++) {
                var detailCampus = listCampus[i].data()! as Map<String, dynamic>;

                String title = detailCampus["nama"];
                String snipet = detailCampus["categori"];
                double lat = double.parse(detailCampus["latitude"]);
                double long = double.parse(detailCampus["longitude"]);

                LatLng latlong = LatLng(lat, long);
                MarkerId markerId = MarkerId(detailCampus["latitude"] + detailCampus["longitude"]);

                controller.addMarker(markerId, title, snipet, latlong);
              }
              return Stack(
                children: [
                  Container(
                    height: Get.height,
                    width: Get.width,
                    child: GoogleMap(
                      mapType: MapType.normal,
                      initialCameraPosition: CameraPosition(target: LatLng(-7.6893549, 110.2408421), zoom: 8),
                      onMapCreated: (GoogleMapController controller) {
                        if (!_controller.isCompleted) {
                          _controller.complete(controller);
                        }
                      },
                      markers: Set<Marker>.of(controller.allMarkers),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Container(
                      margin: EdgeInsets.symmetric(vertical: 25),
                      height: 150,
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        itemCount: listCampus?.length,
                        itemBuilder: ((context, index) {
                          var detailCampus = listCampus[index].data()! as Map<String, dynamic>;
                          return InkWell(
                            onTap: () async {
                              final GoogleMapController controller = await _controller.future;
                              var lat = double.tryParse(detailCampus['latitude']) ?? 0;
                              var long = double.tryParse(detailCampus['longitude']) ?? 0;
                              controller.animateCamera(
                                CameraUpdate.newCameraPosition(
                                  CameraPosition(target: LatLng(lat, long), zoom: 18, tilt: 50, bearing: 45),
                                ),
                              );
                            },
                            child: Container(
                              width: 350,
                              height: 150,
                              margin: EdgeInsets.only(right: 12),
                              decoration: BoxDecoration(
                                color: Color(0xffF5f5f5),
                                borderRadius: BorderRadius.circular(16),
                              ),
                              child: Row(
                                children: [
                                  Container(
                                    padding: EdgeInsets.all(16),
                                    child: Icon(
                                      Icons.school,
                                      size: 50,
                                    ),
                                  ),
                                  SizedBox(width: 12),
                                  Column(
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      SizedBox(height: 90),
                                      Text(
                                        "${detailCampus["nama"]}",
                                        overflow: TextOverflow.ellipsis,
                                        softWrap: false,
                                        style: GoogleFonts.signika(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 16,
                                        ),
                                      ),
                                      SizedBox(height: 5),
                                      Text(
                                        "${detailCampus["categori"]}",
                                        style: GoogleFonts.signika(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 14,
                                          color: Colors.grey,
                                        ),
                                      ),
                                    ],
                                  ),
                                ],
                              ),
                            ),
                          );
                        }),
                      ),
                    ),
                  ),
                ],
              );
            } else {
              return Center(
                child: Text("Error"),
              );
            }
          }),
    );
  }
}

内容的提问来源于stack exchange,提问作者Esa Juniarto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:10:21