Creating a new map using key value pairs, not saving - android

Im decoding a json and transforming it in a variable of type map [string , List < LatLng>] and trying to retun it as the code of this function, howevwer im unable to save it as a map in the variable _polyFinal:
static getPoligoni() async {
http.Response _response = await http.get('$api/posizione/poligoni',
headers: {'Authorization': '${dataController.tokenBearer.value}'});
if (_response.statusCode == 200) {
Map<String, dynamic> _json = jsonDecode(_response.body);
var _poly = Map.from(_json["Poligoni"]).map(
(k, v) {
return MapEntry<String, List<String>>(
k,
List<String>.from(
v.map((x) => x),
),
);
},
);
List<String> _verticiRaw;
List<LatLng> _vertici = [];
Map<String, List<LatLng>> _polyFinal = {};
for (String key in _poly.keys) {
// print(_verticiRaw);
_verticiRaw?.clear();
_verticiRaw = _poly[key];
for (int i = 0; i < _verticiRaw.length; i++) {
print(i);
var _posVirgola = _verticiRaw[i].indexOf(',');
String posx, posy;
posx = _verticiRaw[i].substring(0, _posVirgola);
posy = _verticiRaw[i].substring(_posVirgola + 1);
var lat = double.tryParse(posx);
var lon = double.tryParse(posy);
_vertici.add(LatLng(lat, lon));
}
print(key);
print(_vertici);
_polyFinal.putIfAbsent(key, () => _vertici);
_vertici?.clear();
}
dataController.showLoadingStatus(false);
// print(_polyFinal);
// return _polyFinal;
If I try to print the polyFinal variable at the end of the cycle i get an empty map, And if I print the variable during the cycle every key-value pair get transformed in the following
key --> last vertici value
I tried to chek the values of both key and vertici and they are different every time the cycle is run.
Any help understanding this behavior is greatly appreciated,
Best Regards.

Resolved by putting
_polyFinal.putIfAbsent(key, () => _vertici.toList());
Maybe _vertici is just a pointer and not the value itself.

Related

type 'string' is not a subtype of type 'list<latlng>'

I try to show map polygon. I get list of LatLng data from json.
var map = widget.list[widget.index]['map'];
Data is already decoded.
Sample:
Set<Polygon> myPolygon() {
Set<Polygon> polygonSet = new Set();
polygonSet.add(Polygon(
polygonId: PolygonId('test'),
points: map,
strokeWidth: 2,
strokeColor: Colors.blue,
fillColor: Colors.blue.withOpacity(0.4),));
return polygonSet;
}
This code show error : type 'string' is not a subtype of the 'List<LatLng>'
I want output like this:
you need to pass List<LatLng> to the points of PolyLine make sure you are getting List inside this var map = widget.list[widget.index]['map'];
I don't know this is a correct method or not but it works for me.
Remove Latlng & brackets replace by ", then decode the data. after need count of data so I use count variable
var mapdata1 = map.replaceAll('LatLng(', '"');
var mapdata2 = mapdata1.replaceAll(')', '"');
var mapdata3 = mapdata2.replaceAll(',]', ']');
var mapdata4 = json.decode(mapdata3);
int count = mapdata4.length;
then created list latLang variable
List<LatLng> latlang =new List();
created for loop to fetch list data
for (var i = 0; i <= (count-1); i++) {
List<String> latlong = mapdata4[(i)].split(",");
double latitude = double.parse(latlong[0]);
double longitude = double.parse(latlong[1]);
latlang.add(LatLng(latitude, longitude));
}
if need to check the output
print(latlang);
give latLang variable to polygon points
Set<Polygon> myPolygon() {
Set<Polygon> polygonSet = new Set();
polygonSet.add(Polygon(
polygonId: PolygonId('test'),
points: latlang,
strokeWidth: 2,
strokeColor: Colors.grey,
fillColor: Colors.grey.shade700.withOpacity(0.4),));
return polygonSet;
}

how can I convert Google sheets values (lat and long, two columns) to double for mapping?

I have a google sheet containing an unknown number of lat and long points along with a name identifier.
I can get names lat and long to print. However, I cant' seem to get them to plot because I need a "double" type, and all I can get is a map string string type. Is there any way to make this work?
Code:
Iterable markers = [];
var latstr = (sheet.values.map.column(3)); toString(); //latitude
var lngstr = (sheet.values.map.column(4)); toString(); //longitude
List<dynamic> names = [];
List<double> lat = [];
List<double> lng = [];
for (var i = 0; i < 10; i++) {
names.add(await sheet.values.map.column(2));
lat.add(await (sheet.values.map.column(3)));
lng.add(await sheet.values.map.column(4));
}
setState(() async {
_markers.addAll([
Marker(
markerId: MarkerId("[0]"),
infoWindow: InfoWindow(title: 'test 1' + " " + "test"),
position: LatLng(lat, lng)),
]
);
});
}
I also don't know if the markers.addAll function will work at all. Probably not. I could really use some help with that as well, please.

How to combine loop result in dart

Hello i have a simple for loop what i want to combine the loop results into 1 string separated with a comma
String loc;
for(var q=0; q<2; q++){
userData = res;
loc = userData[q]['location'];
print(loc); //value in first loop is location A value in first second loop is location B i want to combine them on 1 string
}
If you want just append in String then
void main() {
String loc="";
List<String> locs = ["a","d","B","C"];
for(var q=0; q<2; q++){
loc = (loc.length>0? (loc+", ") : loc)+ (locs[q] ?? " ");
}
print(loc);
}
The traditional way would be to collect the strings into a string buffer, and manually add the comma:
var buffer = StringBuffer();
String separator = ""; // Avoid leading comma.
for (var data in userData) {
buffer..write(separator)..write(data["location"]);
separator = ",";
}
var loc = buffer.toString();
Another approach is to collect the values into a list and then use the join method:
var loc = [for (var data in userData) data["location"]].join(",");
That's probably more convenient in most cases, except when you need to do fancy computation on each element.
I have avoided using the for(;;) loop since you don't actually use the index for anything except accessing the user data. Then it's better to just for/in over the list elements directly.
Try ForEach
void main() {
List<String> places = ['New York', 'London', 'Berlin'];
String linearPlace = '';
places.forEach((thePlace) {
linearPlace = linearPlace + thePlace + ", ";
});
print(linearPlace);
//output: New York, London, Berlin,
// In case of Map
Map<String, String> countryCapitalsMap = {'Austria': 'Vienna',
'Armenia': 'Yerevan', 'India': 'Delhi'};
String countryWithCap = '';
countryCapitalsMap.forEach((key, value) {
countryWithCap = countryWithCap + key + ': ' + value + "\n";
});
print(countryWithCap);
// output:
// Austria: Vienna
// Armenia: Yerevan
// India: Delhi
}

Whatsapp-like app

i am developing an app like "whatsapp" for which i want display contacts on my content (between header and footer) from my android phone so what can i do that task?
i tried this but it doesnt work.
function displayContact1() {
alert('Clicked');
var options = new ContactFindOptions();
options.filter="";
options.multiple=true;
var filter = [ "displayName", "phoneNumbers", "photos" ];
navigator.contacts.find(filter, displayContact, onContactError, options);
var myContacts = new Object();
// Default image path for the profile image
var defaultImagePath = $("#defaultImagePath").attr('src');
for (var i=0; i<contacts.length; i++)
{
if( contacts[i].phoneNumbers == null )
continue;
// Checks for the image
var img = contacts[i].photos != null ? contacts[i].photos[0].value : defaultImagePath;
if(contacts[i].phoneNumbers.length)
for (var j=0; j<contacts[i].phoneNumbers.length; j++)
{
var pNumber = contacts[i].phoneNumbers[j].value;
var name = contacts[i].displayName != null ? contacts[i].displayName: "No name";
// To sort the names based on the starting letter
// Stores the names in that array
var index = name.substring(0,1).toUpperCase();
if (typeof myContacts[index] == 'undefined')
{
myContacts[index] = new Array();
}
// cuts the large names
if( name.length > 35 )
{
name = name.substr(0,35)+"...";
}
// Push every details into an array.
myContacts[index].push({"name":name, "pNumber": pNumber, "img": img} );
}
}
var arrayKeys = new Array();
for (var key in myContacts )
{
arrayKeys.push( key );
}
// Sorts the array based on the key A, B , C etc
arrayKeys = arrayKeys.sort();
for( i = 0 ; i < arrayKeys.length ; i++ )
{
var records = myContacts[ arrayKeys[i] ];
$("#contacts").append ("<li class='letter-head'>"+ arrayKeys[i]+"</li>");
// Sort each names
records = records.sort( sortNames );
for( var r_key in records )
{
$("#contacts").append ( "<li><img src='"+ records[r_key].img+"' /> <span class='contact-name'>"+records[r_key].name + "</span><span class='contact-number'>" + records[r_key].pNumber + "</span></li>");
}
}
hide_loader();
$('.addressBook').effect("slide", {direction: "right"}, 500);
}
function sortNames(a, b )
{
return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
}
Please look up the Android Developer Site before asking next time.
Google can help here too.
There's a "Contact Managet" Sample from Google or THIS one.
Here's how you read the contact data: LINK
Here's how you create a custom listview: LINK
Here's a tutorial for a whole contacts list: LINK

How to retrieve more than 1000 rows from Parse.com?

I have been using Parse to retrieve a data for a list view. Unfortunately they limit requests to 100 by default to a 1000 max. I have well over that 1000 max in my class. I found a link on the web which shows a way to do it on iOS but how would you do it on Android? Web Link
I am currently adding all the data into a arraylist in a loop until all items are complete (100) then adding them to the list
I have figured out how to achieve my goal:
Declare Global Variable
private static List<ParseObject>allObjects = new ArrayList<ParseObject>();
Create Query
final ParseQuery parseQuery = new ParseQuery("Objects");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());
Callback for Query
int skip=0;
FindCallback getAllObjects(){
return new FindCallback(){
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
allObjects.addAll(objects);
int limit =1000;
if (objects.size() == limit){
skip = skip + limit;
ParseQuery query = new ParseQuery("Objects");
query.setSkip(skip);
query.setLimit(limit);
query.findInBackground(getAllObjects());
}
//We have a full PokeDex
else {
//USE FULL DATA AS INTENDED
}
}
};
}
Here is a JavaScript version without promises..
These are the global variables (collections are not required, just a bad habit of mine)..
///create a collection of cool things and instantiate it (globally)
var CoolCollection = Parse.Collection.extend({
model: CoolThing
}), coolCollection = new CoolCollection();
This is the "looping" function that gets your results..
//recursive call, initial loopCount is 0 (we haven't looped yet)
function getAllRecords(loopCount){
///set your record limit
var limit = 1000;
///create your eggstra-special query
new Parse.Query(CoolThings)
.limit(limit)
.skip(limit * loopCount) //<-important
.find({
success: function (results) {
if(results.length > 0){
//we do stuff in here like "add items to a collection of cool things"
for(var j=0; j < results.length; j++){
coolCollection.add(results[j]);
}
loopCount++; //<--increment our loop because we are not done
getAllRecords(loopCount); //<--recurse
}
else
{
//our query has run out of steam, this else{} will be called one time only
coolCollection.each(function(coolThing){
//do something awesome with each of your cool things
});
}
},
error: function (error) {
//badness with the find
}
});
}
This is how you call it (or you could do it other ways):
getAllRecords(0);
IMPORTANT None of the answers here are useful if you are using open
source parse server then it does limit 100 rows by default but you can
put any value in query,limit(100000) //WORKS
No need for recursive
calls just put the limit to number of rows you want.
https://github.com/parse-community/parse-server/issues/5383
JAVA
So after 5 years, 4 months the above answer of #SquiresSquire needed some changes to make it work for me, and I would like to share it with you.
private static List<ParseObject>allObjects = new ArrayList<ParseObject>();
ParseQuery<ParseObject> parseQuery = new ParseQuery<ParseObject>("CLASSNAME");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());
FindCallback <ParseObject> getAllObjects() {
return new FindCallback <ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
allObjects.addAll(objects);
int limit = 1000;
if (objects.size() == limit) {
skip = skip + limit;
ParseQuery query = new ParseQuery("CLASSNAME");
query.setSkip(skip);
query.setLimit(limit);
query.findInBackground(getAllObjects());
}
//We have a full PokeDex
else {
//USE FULL DATA AS INTENDED
}
}
}
};
In C# I use this recursion:
private static async Task GetAll(int count = 0, int limit = 1000)
{
if (count * limit != list.Count) return;
var res = await ParseObject.GetQuery("Row").Limit(limit).Skip(list.Count).FindAsync();
res.ToList().ForEach(x => list.Add(x));
await GetAll(++count);
}
JS version:
function getAll(list) {
new Parse.Query(Row).limit(1000).skip(list.length).find().then(function (result) {
list = list.concat(result);
if (result.length != 1000) {
//do here something with the list...
return;
}
getAll(list);
});
}
Usage: GetAll() in C#, and getAll([]) in JS.
I store all rows from the class Rowin the list. In each request I get 1000 rows and skip the current size of the list. Recursion stops when the current number of exported rows is different from the expected.
**EDIT : Below answer is redundant because open source parse server doesn't put any limit on max rows to be fetched
//instead of var result = await query.find();
query.limit(99999999999);//Any value greater then max rows you want
var result = await query.find();**
Original answer:
Javascript / Cloud Code
Here's a clean way working for all queries
async function fetchAllIgnoringLimit(query,result) {
const limit = 1000;
query.limit(limit);
query.skip(result.length);
const results = await query.find();
result = result.concat(results)
if(results.length === limit) {
return await fetchAllIgnoringLimit(query,result );
} else {
return result;
}
}
And here's how to use it
var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
//instead of var result = await query.find();
var result = await fetchAllIgnoringLimit(query,new Array());
console.log("got "+result.length+" rows")
YAS (Yet Another Solution!) Using async() and await() in javascript.
async parseFetchAll(collected = []) {
let query = new Parse.Query(GameScore);
const limit = 1000;
query.limit(limit);
query.skip(collected.length);
const results = await query.find();
if(results.length === limit) {
return await parseFetchAll([ ...collected, ...results ]);
} else {
return collected.concat(results);
}
}
A Swift 3 Example:
var users = [String] ()
var payments = [String] ()
///set your record limit
let limit = 29
//recursive call, initial loopCount is 0 (we haven't looped yet)
func loadAllPaymentDetails(_ loopCount: Int){
///create your NEW eggstra-special query
let paymentsQuery = Payments.query()
paymentsQuery?.limit = limit
paymentsQuery?.skip = limit*loopCount
paymentsQuery?.findObjectsInBackground(block: { (objects, error) in
if let objects = objects {
//print(#file.getClass()," ",#function," loopcount: ",loopCount," #ReturnedObjects: ", objects.count)
if objects.count > 0 {
//print(#function, " no. of objects :", objects.count)
for paymentsObject in objects {
let user = paymentsObject[Utils.name] as! String
let amount = paymentsObject[Utils.amount] as! String
self.users.append(user)
self.payments.append(amount)
}
//recurse our loop with increment because we are not done
self.loadAllPaymentDetails(loopCount + 1); //<--recurse
}else {
//our query has run out of steam, this else{} will be called one time only
//if the Table had been initially empty, lets inform the user:
if self.users.count == 1 {
Utils.createAlert(self, title: "No Payment has been made yet", message: "Please Encourage Users to make some Payments", buttonTitle: "Ok")
}else {
self.tableView.reloadData()
}
}
}else if error != nil {
print(error!)
}else {
print("Unknown Error")
}
})
}
adapted from #deLux_247's example above.
You could achieve this using CloudCode... Make a custom function you can call that will enumerate the entire collection and build a response from that but a wiser choice would be to paginate your requests, and fetch the records 1000 (or even less) at a time, adding them into your list dynamically as required.
GENERIC VERSION For SWIFT 4:
Warning: this is not tested!
An attempt to adapt nyxee's answer to be usable for any query:
func getAllRecords(for query: PFQuery<PFObject>, then doThis: #escaping (_ objects: [PFObject]?, _ error: Error?)->Void) {
let limit = 1000
var objectArray : [PFObject] = []
query.limit = limit
func recursiveQuery(_ loopCount: Int = 0){
query.skip = limit * loopCount
query.findObjectsInBackground(block: { (objects, error) in
if let objects = objects {
objectArray.append(contentsOf: objects)
if objects.count == limit {
recursiveQuery(loopCount + 1)
} else {
doThis(objectArray, error)
}
} else {
doThis(objects, error)
}
})
}
recursiveQuery()
}
Here's my solution for C# .NET
List<ParseObject> allObjects = new List<ParseObject>();
ParseQuery<ParseObject> query1 = ParseObject.GetQuery("Class");
int totalctr = await query1.CountAsync()
for (int i = 0; i <= totalctr / 1000; i++)
{
ParseQuery<ParseObject> query2 = ParseObject.GetQuery("Class").Skip(i * 1000).Limit(1000);
IEnumerable<ParseObject> ibatch = await query2.FindAsync();
allObjects.AddRange(ibatch);
}

Categories

Resources