【问题标题】:Re-using the same StatefulWidget in Flutter在 Flutter 中重用相同的 StatefulWidget
【发布时间】:2020-10-13 16:54:45
【问题描述】:

我想在 Flutter 的多个不同页面中重用同一个 StatefulWidget。在下面的示例中,我希望不为每个页面重建 MyGoogleMap。当我使用 TabBar 导航到第二页时,它使用了另一个新版本的 MyGoogleMap。我尝试使用全局键并加载相同的实例,但只加载了几秒钟,然后我收到相同键被使用两次的错误。

import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';

const double CAMERA_TILT = 0;
const double CAMERA_BEARING = 0;
const LatLng SOURCE_LOCATION = LatLng(42.747932, -71.167889);
const LatLng DEST_LOCATION = LatLng(37.422, -122.084);

class MyGoogleMap extends StatefulWidget {
  const MyGoogleMap({Key key}) : super(key: key);  // NEW CONSTRUCTOR

  @override
  State<MyGoogleMap> createState() => MyGoogleMapState();
}

class MyGoogleMapState extends State<MyGoogleMap> {

  double CAMERA_ZOOM = 16;
  CameraPosition initialCameraPosition;

  //Map controller
  Completer<GoogleMapController> _controller = Completer();
  GoogleMapController controller;

  //Markers
  Set<Marker> _markers = Set<Marker>();

  Set<Polyline> _polylines = Set<Polyline>();

  // the user's initial location and current location
  LocationData currentLocation;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    initialCameraPosition = CameraPosition(
        zoom: CAMERA_ZOOM,
        tilt: CAMERA_TILT,
        bearing: CAMERA_BEARING,
        target: SOURCE_LOCATION);
    if (currentLocation != null) {
      initialCameraPosition = CameraPosition(
          target: LatLng(currentLocation.latitude, currentLocation.longitude),
          zoom: CAMERA_ZOOM,
          tilt: CAMERA_TILT,
          bearing: CAMERA_BEARING);
    }
    return Container(
      height: 400,
      child: GoogleMap(
          mapToolbarEnabled: false,
          myLocationEnabled: true,
          compassEnabled: true,
          tiltGesturesEnabled: false,
          markers: _markers,
          polylines: _polylines,
          mapType: MapType.normal,
          initialCameraPosition: initialCameraPosition,
          onMapCreated: (GoogleMapController controller) {
            //Change this to change styles
            // controller.setMapStyle(Utils.DarkStyle);
            _controller.complete(controller);
          })
    );
  }

}
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);

    return Scaffold(
      resizeToAvoidBottomPadding: false,
      extendBodyBehindAppBar: true,
      extendBody: true,
      body: Container(
          height: SizeConfig.blockSizeVertical * 100,
          width: SizeConfig.blockSizeHorizontal * 100,
          decoration: (selectedNavigationIndex == 3
              ? backgrounds.dark
              : backgrounds.normal),
          child: Column(children: <Widget>[
            TopBar(),
            IndexedStack(
              children: <Widget>[
                MyGoogleMap(),
                MyGoogleMap(),
              ],
              index: selectedNavigationIndex,
            ),
            BottomBar(
                this.selectedNavigationIndexCallback, selectedNavigationIndex),
          ])),
    );
  }

  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);

    return Scaffold(
      resizeToAvoidBottomPadding: false,
      extendBodyBehindAppBar: true,
      extendBody: true,
      body: Container(
          height: SizeConfig.blockSizeVertical * 100,
          width: SizeConfig.blockSizeHorizontal * 100,
          decoration: (selectedNavigationIndex == 3
              ? backgrounds.dark
              : backgrounds.normal),
          child: Column(children: <Widget>[
            TopBar(),
            IndexedStack(
              children: <Widget>[
                MyGoogleMap(key: _MyGoogleMapState),
                MyGoogleMap(key: _MyGoogleMapState),
              ],
              index: selectedNavigationIndex,
            ),
            BottomBar(
                this.selectedNavigationIndexCallback, selectedNavigationIndex),
          ])),
    );
  }

【问题讨论】:

  • 绝对有更好的方法,但如果你找不到任何东西,你可能会使用 Provider 或 GetIt 并以这种方式获取相同的小部件,尽管提供小部件的状态而不是实际的小部件会好得多。
  • 嗨,也许可以为我提供一些示例代码。如何将小部件的状态传递给另一个小部件?

标签: flutter dart widget


【解决方案1】:

如果您想通过不同的路由传递数据/状态(如果我正确阅读了问题),请参阅https://flutter.dev/docs/cookbook/navigation/passing-data。但是,如果您希望同一小部件​​树的不同部分具有相同的状态,provider 通常是首选方法。我更喜欢GetIt,因为它与依赖注入相似,但如果你不知道这意味着什么,请坚持使用提供者。

【讨论】:

    猜你喜欢
    • 2020-12-18
    • 2021-08-18
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2019-10-09
    • 2021-04-08
    • 2020-10-01
    相关资源
    最近更新 更多