al246
al246

Reputation: 230

Lost connection to device. Exited (sigterm) - Flutter Crash

My Flutter app is crashing on loading

It operates a FutureBuilder and I believe this to be where the issue comes from.

My app makes an API Call and returns the data to a map marker.

When i have the FutureBuilder return a list view it works fine.

However, when i change it to return a Stack containing my Map SDK and the buttons to call the API it crashes on start up.

Relevant code is below, thank you!

class HomePage extends StatefulWidget { 

  @override
  _HomePageState createState() => _HomePageState();
}
 

class _HomePageState extends State<HomePage> {
  Future<Stations> stations;
  BuildContext _context;
  MapMarkerExample _mapMarkerExample; 
  


  @override
  void initState() {
   stations = API_Call().fetchStations(); 
   super.initState();
  }
  


  @override
  Widget build(BuildContext context) {
    return Scaffold(
         appBar: AppBar(
          title: Text('Example 1'),
        ),
        
      body: Container(
 
        child: FutureBuilder<Stations>(
          future: stations,
       
            builder: (context, snapshot) {
     
        if (snapshot.hasError) {
          return Text("Error");
        }
  
        if (snapshot.connectionState == ConnectionState.done) {
          return 
          
          Stack(
          children: [
            HereMap(onMapCreated: _onMapCreated),
          

            Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    button('Stations Near Me', _anchoredMapMarkersButtonClicked),
                    button('Clear', _clearButtonClicked),
                  ],
                ),
              ],
            ),
          ],
            );
        }
        
        return Text("Loading");
           
           

            }
        ) 
      )
        );
           }

api_call.dart

class API_Call {

Future<Stations> fetchStations() async {
    var client = http.Client();

      final response = await client.get(
      'https://transit.hereapi.com/v8/stations?in=x,-x&return=transport&apiKey=API_KEY');
   
    if (response.statusCode == 200) {
    return Stations.fromJson(jsonDecode(response.body)); 
  } else {
    throw Exception('Failed to load stations');
  }
    }
    }

api_manager.dart

 typedef ShowDialogFunction = void Function(String title, String message);

 class MapMarkerExample{
 
    
  void showAnchoredMapMarkers() { 
  print('step5');
  
   GeoCoordinates geoCoordinates = _callGeoCoordinates();
           // use the coords .. to add a marker
           _addCircleMapMarker(geoCoordinates, 0);
           _addPOIMapMarker(geoCoordinates, 1);
           print('step6');
  } 

    
 GeoCoordinates _callGeoCoordinates() {
   print('step7');
   var stations;

   Future<Stations> fetchStations() async {
       stations = await API_Call().fetchStations(); 
       for (Station stations in stations) {
           GeoCoordinates geoCoordinates = GeoCoordinates (stations.place.location.lat, stations.place.location.lng);
           // use the coords .. to add a marker
           _addCircleMapMarker(geoCoordinates, 0);
           _addPOIMapMarker(geoCoordinates, 1);
           } 
        }
    }


  HereMapController _hereMapController;
  List<MapMarker> _mapMarkerList = [];
  MapImage _poiMapImage;
  MapImage _circleMapImage;
  ShowDialogFunction _showDialog;
  List<MapMarker3D> _mapMarker3DList = [];
   
   MapMarkerExample(ShowDialogFunction showDialogCallback, HereMapController hereMapController) {
    _showDialog = showDialogCallback;
    _hereMapController = hereMapController;

    double distanceToEarthInMeters = 8000;
    _hereMapController.camera.lookAtPointWithDistance(
      GeoCoordinates(x, -x), distanceToEarthInMeters);

    // Setting a tap handler to pick markers from map.
    _setTapGestureHandler();

    _showDialog("Note", "Tap markers for more.");
    }




  void clearMap() {
    for (var mapMarker in _mapMarkerList) {
      _hereMapController.mapScene.removeMapMarker(mapMarker);
    }
    _mapMarkerList.clear();

    for (var mapMarker3D in _mapMarker3DList) {
      _hereMapController.mapScene.removeMapMarker3d(mapMarker3D);
    }
    _mapMarker3DList.clear();
  }

  Future<void> _addPOIMapMarker(GeoCoordinates geoCoordinates, int drawOrder) async {
    // Reuse existing MapImage for new map markers.
    if (_poiMapImage == null) {
      Uint8List imagePixelData = await _loadFileAsUint8List('assets/poi.png');
      _poiMapImage = MapImage.withPixelDataAndImageFormat(imagePixelData, ImageFormat.png);
    }

    Anchor2D anchor2D = Anchor2D.withHorizontalAndVertical(0.5, 1);

    MapMarker mapMarker = MapMarker.withAnchor(geoCoordinates, _poiMapImage, anchor2D);
    mapMarker.drawOrder = drawOrder;

    Metadata metadata = new Metadata();
    metadata.setString("key_poi", "Next Departures");
    mapMarker.metadata = metadata;

    _hereMapController.mapScene.addMapMarker(mapMarker);
    _mapMarkerList.add(mapMarker);
  }

  Future<void> _addCircleMapMarker(GeoCoordinates geoCoordinates, int drawOrder) async {
    // Reuse existing MapImage for new map markers.
    if (_circleMapImage == null) {
      Uint8List imagePixelData = await _loadFileAsUint8List('assets/circle.png');
      _circleMapImage = MapImage.withPixelDataAndImageFormat(imagePixelData, ImageFormat.png);
    }
    
    MapMarker mapMarker = MapMarker(geoCoordinates, _circleMapImage);
    mapMarker.drawOrder = drawOrder;

    _hereMapController.mapScene.addMapMarker(mapMarker);
    _mapMarkerList.add(mapMarker);
  }

  Future<Uint8List> _loadFileAsUint8List(String assetPathToFile) async {
    // The path refers to the assets directory as specified in pubspec.yaml.
    ByteData fileData = await rootBundle.load(assetPathToFile);
    return Uint8List.view(fileData.buffer);
  }

  void _setTapGestureHandler() {
    _hereMapController.gestures.tapListener = TapListener.fromLambdas(lambda_onTap: (Point2D touchPoint) {
      _pickMapMarker(touchPoint);
    });
  }

  void _pickMapMarker(Point2D touchPoint) {
    double radiusInPixel = 2;
    _hereMapController.pickMapItems(touchPoint, radiusInPixel, (pickMapItemsResult) {
      // Note that 3D map markers can't be picked yet. Only marker, polgon and polyline map items are pickable.
      List<MapMarker> mapMarkerList = pickMapItemsResult.markers;
      if (mapMarkerList.length == 0) {
        print("No map markers found.");
        return;
      }
    });
  }
    }

Upvotes: 1

Views: 1060

Answers (1)

Huthaifa Muayyad
Huthaifa Muayyad

Reputation: 12373

In api_manager.dart, this looks very suspicous, and you aren't returning anything from this function, it could also explain the error saying future not complete

 Future<Stations> fetchStations() async {
   stations = await API_Call().fetchStations(); 
   
       for (Station stations in stations) {
           GeoCoordinates geoCoordinates = GeoCoordinates (stations.place.location.lat, stations.place.location.lng);
           // use the coords .. to add a marker
           _addPOIMapMarker(geoCoordinates, 1);
           }   

          // GeoCoordinates geoCoordinates = stations.coordinates;
          // _addPOIMapMarker(geoCoordinates, 1);
 
    }
 }

You have to return a Stations object from it, try after your for loop something like return stations;, it could fix your problem, if the error changes, it's also a good start.

Also change your line in future builder to this:

if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) 

And for the meantime, remove this _setTapGestureHandler(). The crash is most likely caused by some memory leak, and from the code posted, it could be explained by listeners.

Upvotes: 1

Related Questions