【问题标题】:StreamBuilder doesn't rebuild after Navigator.pop在 Navigator.pop 之后 StreamBuilder 不会重建
【发布时间】:2019-11-03 10:59:42
【问题描述】:

我有一个跟踪当前用户位置的简单服务:

class LocationService {
  LatLng _lastLocation;
  Location location = Location();

 StreamController<LatLng> _locationController = StreamController<LatLng>();
 Stream<LatLng> get locationStream => _locationController.stream;

  LocationService() {
    location.onLocationChanged().listen((locationData) {
      LatLng location = LatLng(locationData.latitude, locationData.longitude);
      if(_lastLocation == null || _lastLocation != location) {
        _lastLocation = location;
        _locationController.add(location);
      }
    });
  }
}

然后,我正在使用此服务创建一个跟随当前用户位置的地图(感谢flutter_map):

class SelfUpdatingMap extends StatelessWidget {
  final Icon currentPositionIcon;

  final MapController _controller = MapController();

  SelfUpdatingMap({
    this.currentPositionIcon,
  });

  @override
  Widget build(BuildContext context) => StreamBuilder<LatLng>(
        stream: LocationService().locationStream,
        builder: (context, asyncSnapshot) {
          if (asyncSnapshot.hasError || asyncSnapshot.data == null) {
            return Text('Loading...');
          }

          try {
            _controller?.move(asyncSnapshot.data, 18);
          } catch (ignored) {}
          return _createMapWidget(context, asyncSnapshot.data);
        },
      );

  Widget _createMapWidget(BuildContext context, LatLng location) => FlutterMap(
        options: MapOptions(
          center: location,
          zoom: 18,
        ),
        layers: [
          TileLayerOptions(
            urlTemplate: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', // https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png is good too.
            subdomains: ['a', 'b', 'c'],
          ),
          MarkerLayerOptions(
            markers: [
              Marker(
                  width: 40,
                  height: 40,
                  point: location,
                  builder: (contact) => currentPositionIcon,
                ),
            ]
          ),
        ],
        mapController: _controller,
      );
}

然后,我在两个地方使用了SelfUpdating 小部件:

  • 第 1 页第 2 页的祖先。
  • 第3页中,第2页的继任者。

所以情况是这样的:

  1. 我启动了我的应用程序,我在第 1 页。我有我的SelfUpdatingMap
  2. 我打电话给Navigator.pushNamed(context, '/page-2')
  3. 我打电话给Navigator.pushNamed(context, '/page-3')。我还有一个SelfUpdatingMap
  4. 我打了两次Navigator.pop(context),我得到第1页 但是SelfUpdatingMap不再自我更新。

构建器甚至不再被调用。那么请问,这段代码有什么问题?

谢谢!

【问题讨论】:

  • 尝试扩展StatefulWidget并在initState方法中初始化LocationService,也尝试覆盖deactivate/dispose以释放您在自定义State中初始化的资源跨度>
  • @pskink 这就是我在使用StreamBuilder 之前所做的。可悲的是,结果是一样的。

标签: flutter dart stream localization bloc


【解决方案1】:

当您推送并弹出页面后,构建方法不会重新启动。 我在 FlutterBluetoothSerial.instance.onStateChanged() 流中发现了同样的问题,我找到的解决方案是将流添加到本地静态最终变量并使用它而不是每次都调用原始方法(只有在我认为该流是广播流)。

解决方案示例:

class ExampleClass {
    static final Stream<LatLng> locationStream = LocationService().locationStream;
}

class SelfUpdatingMap extends StatelessWidget {
    ...
    @override
    Widget build(BuildContext context) => StreamBuilder<LatLng>(
        stream: ExampleClass.locationStream,
        builder: (context, asyncSnapshot) {
            if (asyncSnapshot.hasError || asyncSnapshot.data == null) {
                return Text('Loading...');
            }
            try {
                _controller?.move(asyncSnapshot.data, 18);
            } catch (ignored) {}
            return _createMapWidget(context, asyncSnapshot.data);
        },
    );
    ...
}

class Page3Widget extends StatelessWidget {
    ...
    @override
    Widget build(BuildContext context) => StreamBuilder<LatLng>(
        stream: ExampleClass.locationStream,
        builder: (context, asyncSnapshot) {
            //do something
        },
    );
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-04
    • 2019-10-10
    • 2019-12-31
    • 2023-03-24
    • 2022-11-15
    • 2020-09-02
    • 2021-10-12
    • 1970-01-01
    相关资源
    最近更新 更多