How to Concatenate Strings & fetch data flutter - flutter

I have problem in api calling i getting a geolocation of current place,i am passing the latitude&longitude
but i having a problem is i need to pass the latitude&longitude to certain format like this lat_11.3054724$75.8744252 so i can't try to concatinate the $ sign along with it,Also i am not getting any data when i pass latitude&longitude data i cannot use in api it throws
unhandled Exception: NoSuchMethodError: The getter 'latitude' was called on null.
E/flutter (27500): Receiver: null
E/flutter (27500): Tried calling: latitude
But i can print the data to Text but not pass to api
Code
Future<String> getMainbanner() async {
var latitude=_currentPosition.latitude.toString();
var longitude=_currentPosition.longitude.toString();
var response = await http.post(Urls.HOME_BANNER,
headers: {"Content-Type": "application/json"},
body: json.encode({
"banner_type": "Main_Banner",
"location": "lat_"+latitude+'$'+longitude,
}),);
Map<String, dynamic> value = json.decode(response.body);
if (response.statusCode == 200) {
var resp = response.body;
Map<String, dynamic> value = json.decode(resp);
var message = value['msg'];
var banner =value['bannerapp'][0];
for (int i = 0; i < banner.length; i++) {
var data = banner[i];
print("Data:"+data);
}
}
else
{
CustomDialogs().showErrorAlert(context, "Main Banner Image NotFound");
}
}
Code for fetching Current location
_getCurrentLocation() {
final Geolocator geolocator = Geolocator()..forceAndroidLocationManager;
geolocator
.getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
.then((Position position) {
setState(() {
_currentPosition = position;
});
}).catchError((e) {
print(e);
});
}

Edit: The problem is, that _currentLocation is still null when you call _currentLocation.latitude, because _getcurrentLocation() needs some time to set it. There are different approaches to make it work, depending on how your architecture looks.
Change _getCurrentLocation() to an async function
Future<void> _getCurrentLocation() async {
final Geolocator geolocator = Geolocator()..forceAndroidLocationManager;
try {
final position = await geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best);
setState(() {
_currentPosition = position;
});
} catch(e) {
print(e);
}
}
And await on it inside getMainbanner
Future<String> getMainbanner() async {
await _getCurrentLocation();
var latitude=_currentPosition.latitude.toString();
var longitude=_currentPosition.longitude.toString();
var response = await http.post(Urls.HOME_BANNER,
headers: {"Content-Type": "application/json"},
body: json.encode({
"banner_type": "Main_Banner",
"location": "lat_"+latitude+'$'+longitude,
}),);
Map<String, dynamic> value = json.decode(response.body);
if (response.statusCode == 200) {
var resp = response.body;
Map<String, dynamic> value = json.decode(resp);
var message = value['msg'];
var banner =value['bannerapp'][0];
for (int i = 0; i < banner.length; i++) {
var data = banner[i];
print("Data:"+data);
}
}
else
{
CustomDialogs().showErrorAlert(context, "Main Banner Image NotFound");
}
}
The problem is the $. $ is a special character in dart strings for interpolation so you have to add an escape \ before it.
See here:
https://dart.dev/guides/language/language-tour#strings
And you can make use of this string interpolation to build your string:
var latitude=_currentPosition.latitude;
var longitude=_currentPosition.longitude;
....
"location":"lat_$latitude\$$longitude"
...
Also, you don't need the toString() for latitude and longitude

Related

Flutter save data using http after get location

I'm new in Flutter. I got an issue where i cannot POST data using http after get location.
This is the code
void postData() async {
prefs = await SharedPreferences.getInstance();
bool isAutoCheckIn = prefs.getBool(helper.ISAUTO_CHECKIN) ?? false;
var sessionId = prefs.getString(helper.SESSION_ID);
var employeeId = prefs.getInt(helper.EMPLOYED_ID).toString();
var _uri = Uri.parse(
helper.CHECK_IN + employeeId);
var header = {"session-id": sessionId!};
try {
if (valid) {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.medium);
var _center = LatLng(position.latitude, position.longitude);
List<Placemark> p = await placemarkFromCoordinates(
_center.latitude, _center.longitude);
Placemark place = p[0];
var address =
"${place.street}, ${place.locality}, ${place.subAdministrativeArea}";
var body = {
"test": address
};
final response = await http.post(_uri, headers: header, body: body);
if (response.statusCode == 200) {
dynamic _data = json.decode(response.body);
}
}
} catch (err) {
throw Exception(err);
}
}
Problem comes after this code
List<Placemark> p = await placemarkFromCoordinates(
_center.latitude, _center.longitude);
It will never reach code below it. I am using http: ^0.13.5 geolocator: ^7.7.1 geocoding: ^2.0.5. Am I doing wrong here? Please kindly help me. Thank you

Can't retrieve more than one info from api in Flutter

I'm trying to fetch both temperature and icon name from Openweathermap api. The problem occurs when I try to to fetch icon(or rather icon name).
It returns an error :
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
And I can't seem to find where the problem is. In other models I have other data types and it works fine, here it doesn't.
When I add icon to model, view returns null for temperature.
Here is code for weather model:
class WeatherData {
int? temp;
String? icon;
WeatherData({
this.temp,
this.icon
});
WeatherData.fromJson(dynamic json) {
var tempInKelvin = json["main"]["temp"];
temp = (tempInKelvin - 273.15).round();
icon = json["weather"]["icon"];
}
}
This is weather service:
class WeatherService {
final apiKey = "7e23369c183254302bda0471cc3f848c";
Future<WeatherData?> getWeatherForLocation(LocationData location) async {
WeatherData? weatherData;
var params = {
"lat": location.lat.toString(),
"lon": location.lon.toString(),
"city": location.city,
"appId": apiKey,
};
var url = Uri.http('api.openweathermap.org', '/data/2.5/weather', params);
Response response = await get(url);
if (response.statusCode == HttpStatus.ok) {
var jsonResponse = jsonDecode(response.body) as Map<String, dynamic>;
weatherData = WeatherData.fromJson(jsonResponse);
print("Request successful: $jsonResponse");
return weatherData;
} else {
print("Request failed with status: ${response.statusCode}");
return weatherData;
}
}
}
This is weather controller:
class WeatherController extends GetxController {
final WeatherService _weatherService = Get.find();
Rxn<LocationData> locationData = Rxn();
Rxn<WeatherData> weatherData = Rxn();
// RxString infoText = "...".obs;
String get address =>
"${locationData.value?.city},${locationData.value?.county}, ${locationData.value?.country}";
String get temperature => "${weatherData.value?.temp}";
// String get icon => "${weatherData.value?.icon}";
#override
void onInit() async {
super.onInit();
await getCurrentLocation();
await getTemperatureForCurrentLocation();
await getWeatherIcon();
}
getCurrentLocation() async {
LocationData? location = await _weatherService.getCurrentLocation();
print(location?.city);
locationData.value = location;
}
getTemperatureForCurrentLocation() async {
if (locationData.value != null) {
weatherData.value=
await _weatherService.getWeatherForLocation(locationData.value!);
// _getInfoText(weatherData.value?.temp);
}
}
}
Looking at their API docs, it seems that weather contains an array of objects (as a result, you need an integer index to figure out which one you want).
https://openweathermap.org/current
To fix it, you can simply opt to always use the first object in the weather array and take the icon/description from that:
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
Which is:
icon = json["weather"][0]["icon"];
Can you please check this:
var tempInKelvin = double.parse(json["main"]["temp"]);
or this if your number is integer:
var tempInKelvin = int.parse(json["main"]["temp"]);

Flutter : How to add more json data to existing Model Class?

I have a scenario where the following function is called again and again whenever the user hits the "Load More" button.
The problem I'm facing is, that it replaces previously loaded data with a new one. Instead, it should add to the bottom of the Listview.Builder
Future fetchData() async{
var url = "url_goes_here";
final response = await http.get(url);
if (response.statusCode == 200) {
var resBody = jsonDecode(response.body);
var data = resBody['data'] as List;
if (data.isNotEmpty) {
setState(() {
listVariable = data
.map<ModelClass>((json) => ModelClass.fromJson(json))
.toList();
});
}
}
}
List<ModelClass> listVariable =List<ModelClass>(); //describe the object that way.
--------and---------
data.map<ModelClass>((json) {
listVariable.add(ModelClass.fromJson(jsonn));
} )).toList();
You should add received data to your listVariable, not assign a new value. Try this code:
final listVariable = <ModelClass>[];
...
Future fetchData() async {
var url = "url_goes_here";
final response = await http.get(url);
if (response.statusCode == 200) {
var resBody = jsonDecode(response.body);
var data = resBody['data'] as List;
if (data.isNotEmpty) {
final list = data.map<ModelClass>((json) => ModelClass.fromJson(json));
setState(() {
listVariable.addAll(list); // HERE: addAll() instead of assignment
});
}
}
}
I was able to figure out answer myself.
setState(() {
listVariable.addAll(data
.map<ModelClass>((json) => ModelClass.fromJson(json))
.toList();
}));
#Mol0ko and #hasan karaman both are right but #Mol0ko
Makes better sense when you have a set of data to addAll to existing data.

NoSuchMethodError the method was called on Null

in this code below WeatherModel tried to get current location of android phone,
my problem here is once I start runing it show NoSuchMethod Found, and it says reciever is null,
as I tried a lot of debugging just to see where is my problem.
I now understand that my problem is when I create instance of Location() in WeatherModel, longitude and latitude are null, it never gets value and I dont know why...
Sorry for my bad english :(
const apiKey = 'e3653190f2b1d4803287b3074ecfe618';
const apiWeatherURL = 'https://api.openweathermap.org/data/2.5/weather';
class WeatherModel {
Future<dynamic> getLocationWeather() async {
Location location = Location();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = networkHelper.getData();
return weatherData;
}
}
.....
class Location {
double latitude;
double longitude;
Future<void> getCurrentLocation() async {
try {
Position _position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
longitude = _position.longitude;
print(longitude);
latitude = _position.latitude;
print(latitude);
} catch (e) {
print(e);
}
}
}
.........
class NetworkHelper {
NetworkHelper(this.url);
final url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
print(" Sarkawtua $data");
return data;
} else
print("Error ${response.statusCode} keshay Internet");
}
}
Because you instance fields are not updated, so they are null. You have method for getting current location but it's not fired in getLocationWeather.
Future<dynamic> getLocationWeather() async {
Location location = Location();
await location.getCurrentLocation();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = await networkHelper.getData();
return weatherData;
}
Edit: You also must await networkHelper.getData() method to get not Future Object.

Getting this error - type 'Future<dynamic>' is not a subtype of type 'List<dynamic>'

Whenever trying to call future data and trying converting to List, it returns the error
type 'Future' is not a subtype of type 'List'
Tried type-casting, but no help
On HomePage.dart
final getPost = NetworkFile().getPosts();
List posts;
void getPostsList() {
setState(() {
var res = getPost;
posts = res as List<dynamic>;
print(posts);
});
}
On Network.dart
class NetworkFile{
Future<dynamic> getPosts() async {
var response = await http.get('$kBlogURL' + 'posts?_embed');
Iterable resBody = await jsonDecode(response.body.toString());
return resBody;
}
}
You are decoding the response and its a List of type dynamic. There are few method to handle it. You can create a simple PODO class and cast/mapped to it. Or just do like below:
List posts = [];
void getPostsList() async {
final fetchedPosts = await NetworkFile().getPosts();
setState(() {
posts = fetchedPosts;
});
print(posts);
}
Here is a nice article about PODO.
final getPost = NetworkFile().getPosts();
Map posts;
void getPostsList() async {
var res = await getPost;
setState(() {
posts = res as Map<String, dynamic>;
print(posts);
});
}
class NetworkFile {
Future<dynamic> getPosts() async {
var response = await http.get('https://onetechstop.net/wp-json/wp/v2');
var resBody = await jsonDecode(response.body.toString());
return resBody;
}
}