BlocBuilder无法获得新状态中的值。查看更新Flutter

问题描述 投票:0回答:1

我对Flutter / Dart还是很陌生,我正在使用flutter_bloc bloc /存储库模式。我正在努力从bloc方法中的存储库方法中获取值。我的第一种方法(I get null returned value from a method. Flutter)是在存储库方法中侦听Stream<Position>并返回将在我的bloc方法中保留的LatLng。我总是得到null。

因此,我的新方法是使用StreamTransformerStream<Position>转换为Stream<LatLng>,但由于.transform似乎不可用,我被困在编写存储库方法中,并且出现了错误The method 'transform' isn't defined for the class 'Function'。你能看到我做错了吗?一如既往的感谢。

我的两个方法是:

存储库:

    StreamSubscription _positionStreamSubsciption;

    Stream<LatLng> getLocationStream() {
        print('getLocationStream() called');
        print('isTracking was : $isTracking');
        LatLng location;
        Stream<LatLng> locationStream;
        LocationOptions locationOptions = LocationOptions(
            accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0);
        try {
          if (isTracking == true) {
            _positionStreamSubsciption.cancel();
          } else {
            _positionStreamSubsciption = locationManager
                .getPositionStream(locationOptions)
                .listen((Position position) {
              if (position != null) {
                location = LatLng(position.latitude, position.longitude);

                handleData(Position position, EventSink<LatLng> sink) =>
                    sink.add(location);

                final transformer =
                    StreamTransformer<Position, LatLng>.fromHandlers(
                        handleData: handleData);
                return _positionStreamSubsciption.onData.transform(transformer); // .transform trows an ERROR
              }
              print('getLocationStream() location is : $location');
            });
          }

          isTracking = !isTracking;
          print('isTracking is : $isTracking');
        } catch (error) {
          print('startTracking error: $error');
        }
      }

bloc:

    LatLng locationStream;
    StreamSubscription _locationStreamSubscription;


    Stream<MapState> _mapGetLocationStreamToState(
          GetLocationStream event) async* {
        print('_mapGetLocationStreamToState event received : $event');

        _locationStreamSubscription =
            _mapRepository.getLocationStream().listen((LatLng location) {
          locationStream = location;
        });

更新:

在对代码进行了一点摆弄之后,我发现了错误所在:

  1. 在存储库中,我确实设置了一个侦听器,但实际上需要流本身,所以我添加了_positionStream = locationManager.getPositionStream(locationOptions);

  2. StreamTransformerhandleData中,我在侦听器中添加了一个位置,而不是从其参数Stream<LatLng> locationStream中获取该位置。所以我将其更改为Position position

  3. 在集团中,我还必须收听来自handleData(Position position, EventSink<LatLng> sink) => sink.add(LatLng(position.latitude, position.longitude));的位置信息流。现在,由于不可能直接从侦听器作用域内部产生状态,而从作用域外部产生状态只会产生当前流值,并且此后不会更新,因此我不得不使用事件循环。我向该组添加了_mapRepository.getLocationStream()事件,该事件从流中传递到该位置。

  4. 在blocLocationUpdatedmapEventToStatesLocationStream状态和位置中。

现在,状态正在按预期流动,并带有新的位置值。

唯一要解决的问题(我实际上以为我没有)是,I had to react to that event yielding the MapScren不能容纳来自新状态的值,而在[[ C0]。

BlocBuilder不是掌握它的正确方法吗?

更新后的代码是:

BlocBuilder:

_mapController.move(userLocation, 16);

存储库:

LatLng userLocation = (state as LocationStream).location;

bloc:

bloc: MapBloc(mapRepository: _mapRepository),
        builder: (BuildContext context, MapState state) {
          LatLng userLocation = (state as LocationStream).location;
          return Scaffold(
..
flutter stream
1个回答
0
投票

找到了最后一个问题。在Stream<LatLng> getLocationStream() { print('getLocationStream() called'); print('isTracking was : $isTracking'); Stream<LatLng> locationStream; Stream<Position> _positionStream; LocationOptions locationOptions = LocationOptions( accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0); try { if (isTracking == true) { _positionStreamSubsciption.cancel(); } else { _positionStream = locationManager.getPositionStream(locationOptions); handleData(Position position, EventSink<LatLng> sink) => sink.add(LatLng(position.latitude, position.longitude)); final transformer = StreamTransformer<Position, LatLng>.fromHandlers( handleData: handleData); locationStream = _positionStream.transform(transformer); return locationStream; } isTracking = !isTracking; print('isTracking is : $isTracking'); } catch (error) { print('startTracking error: $error'); } } MapState get initialState => LocationStream(locationStream); @override Stream<MapState> mapEventToState(MapEvent event) async* { // user location if (event is GetLocationStream) { print('MapBloc event received : $event'); yield* _mapGetLocationStreamToState(event); } if (event is LocationUpdated) { yield* _mapLocationUpdatedToState(event); } } Stream<MapState> _mapGetLocationStreamToState( GetLocationStream event) async* { print('_mapGetLocationStreamToState event received : $event'); _locationStreamSubscription = _mapRepository.getLocationStream().listen((LatLng location) { locationStream = location; add(LocationUpdated(locationStream)); print( '_mapGetLocationStreamToState() locationStream is: $locationStream '); }); // yield LocationStream(locationStream); } 中,如果您通过一个块,则实际上是在每次UI重建时都在创建一个新的块。

这对于管理局部值的本地块很有用,但是在我的情况下,BlocBuilder是在bloc:中创建的全局块,因此如果我继续在MapBloc中创建一个新的块,则不会获得该值以最后状态传入,结果为空值。不通过任何集团修复它。

main()

希望这会帮助其他人起步,因为Flutter相对较新,并且关于API的详细解释并不多,因此刚开始时很难掌握。例如,《 Geolocator API参考》非常棒。很明显,对每个类和参数都有详细的解释,并有一些代码示例作为后盾..不需要更多,实现它很容易。flutter_bloc并不是很多(有关此问题,请参见BlocBuilder中的bloc参数),但是可以为您提供满足大部分需求的大量项目,因此无论如何您都会找到理解API的方法。干杯。

© www.soinside.com 2019 - 2024. All rights reserved.