我有2个小部件。父级StatefulWidget
在首次满载期间会多次更改状态,而子级StatelessWidget
的构建成本很高。
构建子窗口小部件之所以昂贵,是因为它使用google_maps_flutter
库,该库使用Web视图在屏幕上显示google地图。
如果可能,我希望此子窗口小部件中的build()
函数仅执行一次。
但是,每当由于状态更改而多次构建父窗口小部件时,似乎子窗口小部件也将被多次构建。因此,当屏幕首次加载时,我会看到一些卡顿/滞后的情况。
防止子窗口小部件多次重建的最佳方法是什么?
下面是示例代码。
父小部件
class ParentWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
Completer<GoogleMapController> _controller = Completer();
LocationPosition _myPosition;
@override
void initState() {
super.initState();
initialize();
}
void initialize(){
....// other initialization logic which may call `setState()` multiple times
}
Set<Marker> getMarkers(){
....
}
@override
Widget build(BuildContext context) {
return Scaffold(body: GoogleMapWidget(_controller, _myPosition, getMarkers()));
}
}
子窗口小部件
class GoogleMapWidget extends StatelessWidget {
static const double ZOOM = 15;
final Completer<GoogleMapController> _controller;
final Set<Marker> markers;
final LocationPosition _myPosition;
GoogleMapWidget(this._controller, this._myPosition, this.markers);
@override
Widget build(BuildContext context) {
print("Rebuilt"); // <-- This gets printed multiple times, which is not something I want.
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(_myPosition.lat, _myPosition.lng),
zoom: ZOOM,
),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
markers: markers);
}
}
答案 0 :(得分:0)
每次调用setState时,都会触发重建。在initState中调用它可能不是一个好主意。多次调用是不行的。
Importance of Calling SetState inside initState
为避免多次重建,
在本地字段中初始化所有对象,只有当所有对象准备就绪时,才可以调用setState。
除了在setState中设置变量外,请勿执行其他任何处理。
不要在build方法中触发http / api调用。即使您是,也可以添加条件逻辑以仅在需要时这样做。
在调用setState之前,您可能需要检查对象是否实际更改。
对于Google Maps包,尤其是Google Maps包,请检查MapController方法,因为您可能可以使用提供的方法,而无需设置小部件本身的属性。这样,谷歌地图包就可以确定是否需要setState。