Search code examples
androidflutterdartgoogle-mapschrome-app-developer-tool

Drop down button flutter error exception with Null value


enter image description here

======== Exception caught by widgets library ======================================================= The following assertion was thrown building MyHomePage(dirty, dependencies: [MediaQuery], state: _MyHomePageState#a3bdf(tickers: tracking 1 ticker)): There should be exactly one item with [DropdownButton]'s value: Marker{markerId: MarkerId(First Marker), alpha:enter image description here 1.0, anchor: Offset(0.5, 1.0), consumeTapEvents: false, draggable: false, flat: false, icon: Instance of 'BitmapDescriptor', infoWindow: InfoWindow{title: First Marker, snippet: null, anchor: Offset(0.5, 0.0)}, position: LatLng(37.42267, -122.0838), rotation: 0.0, visible: true, zIndex: 0.0, onTap: null, onDragStart: null, onDrag: null, onDragEnd: null}. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value 'package:flutter/src/material/dropdown.dart': Failed assertion: line 888 pos 15:

'items == null || items.isEmpty || value == null ||
              items.where((DropdownMenuItem<T> item) {
                return item.value == value;
              }).length == 1'


    DropdownButton(
                    value: selectedMarker,
                onChanged: ((Marker? marker) {
                  setState(() {
                    selectedMarker = marker!;
                  });
                  print("selectedmarker value ${selectedMarker}");
                  mapController.moveCamera(CameraUpdate.newLatLng(marker!.position));
                }),
            items: markers.map((marker) {
              return DropdownMenuItem(
                value: marker,
                child: Text(marker.markerId.value),
              );
            }).toList(),
          ),

This is the dropdownbutton widget which is causing the error. Now the thing I want to achieve is that after selecting an item from the menu the Marker on the maps gets selected. that is done. Now if i press directions button then the marker will follow polylinepoints. When i press the button this error occurs. Directions button code is given below:

IconButton(
   onPressed: () async {
         if(selectedMarker.markerId == MarkerId("First Marker")){
           controller = AnimationController(
            duration: const Duration(milliseconds: 1000),
               vsync: this,
               );
                 selectedMarker = markers[0];
       for (int i = 0; i < polylinePoints.length && i + 1 != polylinePoints.length; i = i + 1) {
                                markerAnimation = LatLngTween(
                                    begin: polylinePoints[i],
                                    end: polylinePoints[i + 1])
                                    .animate(controller);
                                markerAnimation.addListener(() {
                                  setState(() {
          Marker marker1 = Marker(markerId: MarkerId("First Marker",
                       ),icon:BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
                                    );
                                    print("This is marker1 ${marker1}");
                                    marker1 = marker1.copyWith(
                                      positionParam: markerAnimation.value,
                                    );
                                    ///will be right back
                                    markers[0] = marker1;
                                    // _addFirstMarker(Variables.point);
                                  });
                                });
                                controller.forward();
                                await Future.delayed(
                                    const Duration(milliseconds: 50));
                              }
                            }
                            if(selectedMarker.markerId == MarkerId("Second Marker")){
                              controller = AnimationController(
                                duration: const Duration(milliseconds: 1000),
                                vsync: this,
                              );
                 selectedMarker = markers[1];
     for (int i = 0; i < polylinePoints1.length && i + 1 != polylinePoints1.length; i = i + 1) {
                                markerAnimation = LatLngTween(
                                    begin: polylinePoints1[i],
                                    end: polylinePoints1[i + 1])
                                    .animate(controller);
                                markerAnimation.addListener(() {
                                  setState(() {
          Marker marker1 = Marker(markerId: MarkerId("Second Marker",
            ),icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
                                    );
                                    marker1 = marker1.copyWith(
                                      positionParam: markerAnimation.value,
                                    );
                                    markers[1] = marker1;
                                    // _addFirstMarker(Variables.point);
                                  });
                                });
                                controller.forward();
                                await Future.delayed(
                                    const Duration(milliseconds: 50));
                              }
                            }
                            if(selectedMarker.markerId == MarkerId("Third Marker")){
                              controller = AnimationController(
                                duration: const Duration(milliseconds: 1000),
                                vsync: this,
                              ); selectedMarker = markers[2];
     for (int i = 0; i < polylinePoints2.length && i + 1 != polylinePoints2.length; i = i + 1) {
                                markerAnimation = LatLngTween(
                                    begin: polylinePoints2[i],
                                    end: polylinePoints2[i + 1])
                                    .animate(controller);
                                markerAnimation.addListener(() {
                                  setState(() {
          Marker marker1 = Marker(markerId: MarkerId("Third Marker",
           ), icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
                                    );
                                    marker1 = marker1.copyWith(
                                      positionParam: markerAnimation.value,
                                    );
                                    markers[2] = marker1;
                                    // _addFirstMarker(Variables.point);
                                  });
                                });
                                controller.forward();
                                await Future.delayed(
                                    const Duration(milliseconds: 50));
                              }
                            }
                          },
                          icon: Icon(Icons.directions))

Solution

  • The value of a DropDownButton must exist among the values of the items.

    When you tap for example the first button you do

    selectedMarker = markers[0];
    

    but some lines below it assign a new marker to it

    markers[0] = marker1;
    

    Now selectedMarker no longer exists inside markers and this is not allowed. I believe should do the

    selectedMarker = markers[0];
    

    right after you do

    markers[0] = marker1;
    

    and not before it. Same with the other ones.