dart 无法使用Future从提供程序更新标记,设置状态时工作正常

wvyml7n5  于 2023-03-15  发布在  其他
关注(0)|答案(2)|浏览(110)

基本上,我从一个json文件中获取标记的数据列表,我不想使用setState,而是使用一个提供程序。一切工作正常,没有错误,但我的标记在flutter_map中没有得到更新
这是主类

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  MapController? osmController;
  Future<void> startParam() async {
    osmController = MapController();
    MarkerListProvider markerListProvider = MarkerListProvider();
    await markerListProvider.loadMarkers();
    //await AirportMarkers.loadMarkers(context);
  }
  @override
  void initState() {
    super.initState();
    startParam();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: [
            SizedBox(
              height: 950,
              child: FlutterMap(
                mapController: osmController!,
                options: MapOptions(
                  center: LatLng(27.7000, 85.3333),
                  zoom: 8,
                  minZoom: 3,
                  // adaptiveBoundaries: true,
                  interactiveFlags: //InteractiveFlag.none
                      InteractiveFlag.pinchZoom | InteractiveFlag.drag,
                ),
                children: [
                  TileLayer(
                      tileProvider: CachedTileProvider(),
                      urlTemplate:
                          //  'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                          'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'),
                  Consumer<MarkerListProvider>(
                      builder: (BuildContext context, value, Widget? child) {
                    return MarkerLayer(markers: value.airportMarkers);
                    // );
                  }),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

这是提供者类

class MarkerListProvider extends ChangeNotifier {
  List<Marker> airportMarkers = [];

  Future<void>  loadMarkers() async {
    double markerWidth = 20;
    double markerHeight = 20;

    // Load the JSON file containing the markers
    final String jsonString =
        await rootBundle.loadString('assets/airport_markers.json');

    // Decode the JSON data into a List of Maps
    final List<dynamic> jsonData = await json.decode(jsonString);

    // Create a List of Markers from the JSON data
    List<Marker> apMarker = jsonData.map((data) {
      final double latitude = data['point']['latitude'];
      final double longitude = data['point']['longitude'];
      final String text = data['text'];

      return Marker(
        width: markerWidth,
        height: markerHeight,
        point: LatLng(latitude, longitude),
        builder: (ctx) => MarkerTap(str: text),
      );
    }).toList();

    // Set the airportMarkers list and return it
    airportMarkers = apMarker;
    notifyListeners();
  }
}

我知道解析没有问题,这是因为当我在主类中使用setState而不使用provider时,所有的标记填充都很好。

Future<void> loadMarkers() async {
   double markerWidth = 20;
  double  markerHeight = 20;

    // Load the JSON file containing the markers
    final String jsonString =
        await rootBundle.loadString('assets/airport_markers.json');

    // Decode the JSON data into a List of Maps
    final List<dynamic> jsonData = json.decode(jsonString);

    // Create a List of Markers from the JSON data
   // List<Marker> apMarker = [];
    apMarker = jsonData.map((data) {
      final double latitude = data['point']['latitude'];
      final double longitude = data['point']['longitude'];
      final String text = data['text'];

      return Marker(
        width: markerWidth,
        height: markerHeight,
        point: LatLng(latitude, longitude),
        builder: (ctx) => MarkerTap(str: text),
      );
    }).toList();
    setState(() {
      
    });
  
  }

这里似乎有什么问题?我的数据很大,包含了世界各地的机场。

toiithl6

toiithl61#

您必须在应用上注册提供程序,然后从上下文获取数据。

在主要:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Preferences.init();
  runApp(const AppState());
}

class AppState extends StatelessWidget {
  const AppState({super.key});

@override
  Widget build(BuildContext context) {
    return MultiProvider(providers: [
      ChangeNotifierProvider(create: (_) => MarkerListProvider(), 
             lazy:true)], child: const MyApp());
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      initialRoute: AppRoutes.initialRoute(),
      routes: AppRoutes.getAppRoutes(),
    );
  }
}

在屏幕上你正在获取数据

@override
  Widget build(BuildContext context) {
    final markersProvider = Provider.of<MarkerListProvider >(context);
    markerListProvider.loadMarkers().then((value){
           //YOUR CODE.

});
       .
       .
       .
     }

还可以考虑使用FutureBuilder()作为基于外部数据的小部件:

FutureBuilder(
    future: markerListProvider.loadMarkers(), builder:
        (BuildContext context, AsyncSnapshot<List<Marker>> snapshot) {
      if (!snapshot.hasData) {
        return const Text("No data available");
      }
      final markers = snapshot.data;
      if (markers!.isEmpty) {
        return const Text("No data available");;
      }
      return ListView.builder(
        itemCount: markers.length,
      itemBuilder: ((context, index) {
            return Text(" ${markers[index].text} - ${markers[index].latitude} , ${markers[index].longitude}");
      })
      );
    }
  ),
ct3nt3jp

ct3nt3jp2#

奇怪的是,我只需要这样做,没有多大意义,但工作。必须示例化loadMarkers与提供者。

@override
  void initState() {
    super.initState();
    startParam();
    MarkerListProvider markerListProvider =
        Provider.of<MarkerListProvider>(context, listen: false);
    markerListProvider.loadMarkers();
    MarkerListProvider markerListProvider2 =
        Provider.of<MarkerListProvider>(context, listen: false);
    markerListProvider2.loadGeoJson();
  }

相关问题