I\'m using geolocator plugin and getting current latitude and longitude but i can\'t load that in initstate of my Flutter Application. It showing Render Error.
As Abbas.M suggestion i'm solving my problem using FutureBuilder Widget.
FutureBuilder Widget: https://www.youtube.com/watch?v=ek8ZPdWj4Qo
I'm declaring variable _future
Future<Position> _future;
I'm calling my async method in the initState
void initState() {
// TODO: implement initState
super.initState();
_future = getCurrentLocation();
}
Using FutureBuilder widget i solved my problem and i'm passing my async function return value to parameter of FutureBuilder widget.
This Condition if(snapshot.connectionState == ConnectionState.done) helps to find our async function completed and returned value or not. if it is in Done state then it means function completed and returned.
If that condition is not satisfied then it means async function is not completed so i'm using CircularProgressIndicator widget to notify user to understand app is loading.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Krish"),
),
body: FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (!snapshot.hasError) {
print(snapshot.data.latitude);
return Stack(children: <Widget>[
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(
snapshot.data.latitude, snapshot.data.longitude),
zoom: 12.0),
onMapCreated: mapCreated,
),
Positioned(
top: 30.0,
left: 15.0,
right: 15.0,
child: Container(
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white),
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter Address',
contentPadding:
EdgeInsets.only(top: 15.0, left: 15.0),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: searchAndNavigate,
iconSize: 30.0,
)),
onChanged: (value) {
searchAddress = value;
},
),
),
),
]);
}
} else {
return Center(child: CircularProgressIndicator());
}
}));
}
Future<Position> getCurrentLocation() async
{
var answer = await Geolocator().getCurrentPosition();
return answer;
}
I tried many ways until I found this way thanks to a kind person who helped on another flutter facebook group. Make sure in your pubspec.yaml you update location to the latest version
dependencies: location: ^2.3.5 Then change it to the following code:
LocationData _currentLocation;
StreamSubscription<LocationData> _locationSubscription;
var _locationService = new Location();
String error;
void initState() {
super.initState();
initPlatformState();
_locationSubscription = _locationService
.onLocationChanged()
.listen((LocationData currentLocation) async {
setState(() {
_currentLocation = currentLocation;
});
});
}
void initPlatformState() async {
try {
_currentLocation = await _locationService.getLocation();
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
}else if(e.code == "PERMISSION_DENIED_NEVER_ASK"){
error = 'Permission denied';
}
_currentLocation = null;
}
Run code snippetReturn to post
You may access longitude and latitude as
_currentLocation.longitude and _currentLocation.latitude
these will return double values. Also, there are more options available at https://pub.dev/packages/location#-readme-tab-
I have almost no idea what's happening but based on the code since you have a .then, before the .then function happen your latitude and longitude are null, and when you have a .then the rest of your code is not awaiting for the future to be resolved. Try initializing the longitude and latitude to some value other than null in your init state so:
void initState() {
// TODO: implement initState
super.initState();
latitude = 0;
longitude = 0;
getCurrentLocation().then((k) {
latitude = k.latitude;
longitude = k.longitude;
setState(() {});
});
}