1

I have a small project in Dart where I'm using the library location. With that library I try to calculate the speed of vehicle using GPS locations. The problem is that I'm getting an error in console every time when I run the project:

The following NoSuchMethodError was thrown building ListenLocationWidget(dirty, state: _ListenLocationState#55ce8):
The getter 'speed' was called on null.
Receiver: null
Tried calling: speed

Here is a link to my small project: https://github.com/flo/VehicleSpeed

Here is my code where I calculate the speed between locations:

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

class ListenLocationWidget extends StatefulWidget {
  const ListenLocationWidget({Key key}) : super(key: key);

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

class _ListenLocationState extends State<ListenLocationWidget> {
  final Location location = Location();

  LocationData _location;
  StreamSubscription<LocationData> _locationSubscription;
  String _error;

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

  Future<void> _listenLocation() async {
    _locationSubscription =
        location.onLocationChanged.handleError((dynamic err) {
      setState(() {
        _error = err.code;
      });
      _locationSubscription.cancel();
    }).listen((LocationData currentLocation) {
      setState(() {
        _error = null;
        _location = currentLocation;
      });
    });
  }

  Future<void> _stopListen() async {
    _locationSubscription.cancel();
  }

  Widget _calculateSpeedBetweenLocations() {
    return Text(
      '${_location.speed != null && _location.speed * 3600 / 1000 > 0 ? (_location.speed * 3600 / 1000).toStringAsFixed(2) : 0} KM/h',
      style: TextStyle(
        color: Colors.lightGreen[500],
        fontSize: 20,
        letterSpacing: 4,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        _calculateSpeedBetweenLocations(),
      ],
    );
  }
}

And here is my HomeScreen:

import 'package:vehicle_speed_demo/location/permissionStatus.dart';
import 'package:vehicle_speed_demo/location/serviceEnabled.dart';
import 'package:vehicle_speed_demo/location/getLocation.dart';
import 'package:vehicle_speed_demo/location/listenLocation.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();
  }

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

  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        backgroundColor: Colors.grey[900],
        appBar: _appBar(),
        body: _buildUI(),
      ),
    );
  }

  Widget _appBar() {
    return AppBar(
      backgroundColor: Colors.purple[800],
      elevation: 0.0,
      title: Text(
        'My App',
        style: TextStyle(
          color: Colors.white,
          fontSize: 30.0,
        ),
      ),
      automaticallyImplyLeading: false,
    );
  }

  Widget _buildUI() {
    return Container(
        child: Padding(
      padding: const EdgeInsets.all(10),
      child: Column(
        children: <Widget>[
          Wrap(
            spacing: 30.0, // gap between sections
            runSpacing: 30.0, // gap between lines
            alignment: WrapAlignment.spaceAround,
            children: <Widget>[
              Divider(color: Colors.white, height: 20),
              _buildSpeedSection(),
            ],
          ),
        ],
      ),
    ));
  }

  Widget _buildSpeedSection() {
    return Container(
      height: 150,
      width: 170,
      child: Column(
        children: <Widget>[
          Text(
            'SPEED',
            style: TextStyle(
              color: Colors.white,
              fontSize: 30,
            ),
          ),
          PermissionStatusWidget(),
          ServiceEnabledWidget(),
          GetLocationWidget(),
          ListenLocationWidget(),
        ],
      ),
    );
  }
}

Any help will be appreciated !

Florentin Lupascu
  • 754
  • 11
  • 30
  • You may also want to look at https://stackoverflow.com/questions/63017280/what-is-a-future-and-how-do-i-use-it, because your problem is that you don't wait for your async calls to finish, so your variable is still null when you use it. – nvoigt Oct 07 '20 at 14:07

1 Answers1

2

Maybe, _location.speed is causing the problem because initially, _location is null. The future takes some time to execute so to summarize, you are trying to access the speed property of _location which is null in the beginning.

Try this:

Widget _calculateSpeedBetweenLocations() {

// Check if location is null
if(_location == null) return Text("Hold on!");

return Text(
  '${_location.speed != null && _location.speed * 3600 / 1000 > 0 ? (_location.speed * 3600 / 1000).toStringAsFixed(2) : 0} KM/h',
  style: TextStyle(
    color: Colors.lightGreen[500],
    fontSize: 20,
    letterSpacing: 4,
  ),
);
Afridi Kayal
  • 2,112
  • 1
  • 5
  • 15