Flutter: Non-nullable instance field 'currentLocation' must be initialised - flutter

I'm getting an error with the new flutter changes on null safety. Am not sure whether I am supposed to add final/late/! in this code.
I have a code to connect to Google Maps and now I want to be able to store the data collected.
Right now I facing an error at the Application Bloc: Non-nullable field 'currentLocation' must be initialized.
import 'package:flutter/material.dart';
import 'package:hawkepedia/services/geolocator_Services.dart';
import 'package:geolocator/geolocator.dart';
class ApplicationBloc with ChangeNotifier {
final geoLocatorService = GeolocatorService();
//Variables
Position currentLocation;
//fire function when the app starts
ApplicationBloc(){
setCurrentLocation();
}
//gets current location
setCurrentLocation() async {
currentLocation = await geoLocatorService.getCurrentLocation();
notifyListeners();
}
}

As it is state in the error, the field causing the issue is currentLocation.
You can:
set it as late meaning you will initilize it during initState for example.
set it a nullable, not sure it is possible in this case, Position? currentLocation. (But it is for primary types)
Initialize it with a neutral value that you know is not initialized yet
Edit:
import 'package:flutter/material.dart';
import 'package:hawkepedia/services/geolocator_Services.dart';
import 'package:geolocator/geolocator.dart';
class ApplicationBloc with ChangeNotifier {
final geoLocatorService = GeolocatorService();
//Variables
late Position currentLocation;
//fire function when the app starts
ApplicationBloc(){
setCurrentLocation();
}
//gets current location
setCurrentLocation() async {
currentLocation = await geoLocatorService.getCurrentLocation();
notifyListeners();
}
}

Related

Listen to changes on a Future object in Flutter

I need to know wether NFC is active or inactive inside the application. I'm using nfc_manager package and riverpod for state management. Here is my providers and ChangeNotifier class:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nfc_manager/nfc_manager.dart';
final nfcProvider = ChangeNotifierProvider.autoDispose<NfcService>((ref) {
return NfcService();
});
final nfcIsAvabilableProvider = StreamProvider.autoDispose<bool>((ref) {
ref.maintainState = true;
final stream = ref.watch(nfcProvider).isAvailable.stream;
return stream;
});
class NfcService extends ChangeNotifier {
NfcManager nfcManager = NfcManager.instance;
StreamController<bool> isAvailable = StreamController.broadcast();
NfcService() {
init();
}
init() async {
isAvailable.addStream(nfcManager.isAvailable().asStream());
}
}
When I close the NFC inside the settings, nfcManager.isAvailable() does not return the new state of NFC availability because it is a future not a stream.
So my question is: how to listen to changes on a future object in Flutter?

variable with late modifier not getting initialized

Here is my provider code for connectivity, where the variable _isOnline will be assigned later.
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
class ConnectivityProvider with ChangeNotifier {
// this will hold the status
late bool _isOnline;
// method to set the initial state and listen
Future<void> updateStatus() async {
// getting the object
Connectivity connectivity = Connectivity();
// getting the status
final ConnectivityResult connectivityResult =
await connectivity.checkConnectivity();
if (connectivityResult == ConnectivityResult.none) {
_isOnline = false;
} else {
_isOnline = true;
}
}
// getter to get the online status
bool get isOnline => _isOnline;
}
I'm assigning the value to the _isOnline in another page's initState:
#override
void initState() {
super.initState();
// getting the initial status of the connection
Provider.of<ConnectivityProvider>(context, listen: false).updateStatus();
}
But I'm still getting an error saying that the variable was not initialized even though I did assign it in the initState:
Can someone please tell me what I'm doing wrong here?
The issue appears because somewhere in your codes call the isOnline when it is still not initialized. You can just change the variable from late bool _isOnline; to bool _isOnline = false; to make sure the internet is not connected as default when users open the app.

How to handle a late variable for a short moment before it is initialized?

In my app, I am using geolocator package to get the current location of the user. Everything works fine besides a second before the map UI loads. The problem is,
late Position currentLocation;
This variable is being set in a second. Before it sets the data, dart throws this error for a very short time:
LateInitializationError: Field 'currentLocation' has not been initialized.
After that, everything goes back to normal. I tried not to use 'late' but then I got this error:
Non-nullable instance field 'currentLocation' must be initialized. Try adding an initializer expression, or a generative constructor that initializes it, or mark it 'late'
I tried using a CircularProgressIndicator in my map UI until it gets the value but it never becomes null anyway... What should I do in this kind of situation?
Here is my entire class if needed:
class ApplicationBloc with ChangeNotifier {
final geoLocatorService = GeoLocatorService();
final placesService = PlacesService();
late Position currentLocation;
List<PlaceSearch> searchResults = [];
ApplicationBloc() {
setCurrentLocation();
}
setCurrentLocation() async {
currentLocation = await geoLocatorService.getCurrentLocation();
notifyListeners();
}
searchPlaces(String searchTerm, double radius) async {
searchResults = await placesService.getAutoComplete(searchTerm, radius);
notifyListeners();
}
}

Flutter Send a post request while waiting for gps data

I'm stuck on my flutter project, I want to send the gps coordinate every time the user open the app to check if its position is on specific place referenced on my base (if yes it send a notification). I have two futures, one of which is dependent on the other (sending needs gps data).
import 'package:http/http.dart' as http;
import 'package:location/location.dart';
import 'dart:convert';
class Islandmenu extends StatelessWidget {
Widget build(BuildContext context) {
......
}
Future<void>getgpscoordinates() async{
final locdata = await Location().getLocation();
List<double> gps= [locdata.latitude,locdata.longitude];
return gps;
}
Future<void>checkUser(gps) async{
const String userurl="*********/input_dbco.php";
final response = await http.post(userurl, body:jsonEncode({
"id": "",
"gps":[gps[0],gps[1]],
"dateco": "",
}));
return response;
}
}//end of class
but it's make my VM crash so i guess i do it in the wrong way ^^.

Flutter Riverpod/Provider: Setting an initial state for a stateNotifier

So I want to have a provider who's initial state will be the a user's location, this is what I have now, is this right?
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/all.dart';
import 'package:location/location.dart';
class MapApiState {
final LocationData userLocation;
MapApiState({#required this.userLocation});
}
class MapNotifier extends StateNotifier<MapApiState> {
static Location _location = Location();
MapNotifier() : super(null) {
_location.getLocation().then((initialState) =>
super.state = MapApiState(userLocation: initialState));
}
}
Is this the right approach? How do I now declare the global provider variable for this? The super(null) worries me. But I can't just put "super(_location.getLocation())"
Also, how should I then instantiate my global provider variable?
Well it almost depends of how you want to apply it in the lifecycle of your app, you can use StreamProvider or FutureProvider to get the location and then pass it to your StateNotifier
final locationProvider = FutureProvider<LocationData>((ref) {
final Location _location = Location();
return _location.getLocation();
});
final singleDetailDealProvider = StateNotifierProvider<MapNotifier>((ref) {
final location = ref.watch(locationProvider);
return MapNotifier(location.data?.value);
});
class MapNotifier extends StateNotifier<MapApiState> {
MapNotifier(LocationData location) : super(location);
}
That way if you want to use the location somewhere else you can call locationProvider without depending on the state of MapNotifier