在 Navigator.pop 之后 StreamBuilder 不会重建
Posted
技术标签:
【中文标题】在 Navigator.pop 之后 StreamBuilder 不会重建【英文标题】:StreamBuilder doesn't rebuild after Navigator.pop 【发布时间】: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 页。我有我的
SelfUpdatingMap
。
我打电话给Navigator.pushNamed(context, '/page-2')
。
我打电话给Navigator.pushNamed(context, '/page-3')
。我还有一个SelfUpdatingMap
。
我打了两次Navigator.pop(context)
,我得到第1页 但是SelfUpdatingMap
不再自我更新。
构建器甚至不再被调用。那么请问,这段代码有什么问题?
谢谢!
【问题讨论】:
尝试扩展StatefulWidget
并在initState
方法中初始化LocationService
,也尝试覆盖deactivate
/dispose
以释放您在自定义State
中初始化的资源跨度>
@pskink 这就是我在使用StreamBuilder
之前所做的。可悲的是,结果是一样的。
【参考方案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
,
);
...
【讨论】:
以上是关于在 Navigator.pop 之后 StreamBuilder 不会重建的主要内容,如果未能解决你的问题,请参考以下文章
在 Navigator.pop 之后 StreamBuilder 不会重建
来自 FutureBuilder 的 Navigator.pop
Flutter 图像在 navigator pop 上再次下载
Navigator.pop() - 如何传递 `context` 以供导航器读取 -