I'm using google maps to show some markers. The markers are download from a database and, at the same time, I get the distancematrix from google api, between the current position of the user and the marker that I get from the database.
My problem is that I was doing this with .get, bloking my ui (I've read that .get blocked the ui:
dataFromAsyncTask = testAsyncTask.get();
Now, I'm trying to do the same without blocking the ui, but I'm not be able to get at the same time, or in a good way, the distance for this markers.
I appreciate some help, please.
This is my code with my old and wrong .get:
for (City city : listCity.getData()) {
geoPoint = city.getLocation();
nameBeach = city.getName();
if (geoPoint == null) {
} else {
latitude = String.valueOf(geoPoint.getLatitude());
longitude = String.valueOf(geoPoint.getLongitude());
startRetrievenDistanceAndDuration();
try {
dataFromAsyncTask = testAsyncTask.get();
} catch (InterruptedException i) {
} catch (ExecutionException e) {
}
mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(nameCity)
.snippet(dataFromAsyncTask)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
}
startRetrievenDistanceAndDuration method:
private void startRetrievenDistanceAndDuration() {
final String url;
testAsyncTask = new DistanceBetweenLocations(new FragmentCallback() {
@Override
public void onTaskDone(String result) {
}
});
url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxx";
testAsyncTask.execute(new String[]{url});
}
public interface FragmentCallback {
public void onTaskDone(String result);
AsyncTask class:
@Override
protected String doInBackground(String... params) {
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder result = null;
String duration = "";
String distance = "";
try {
url=new URL(params[0]);
}catch (MalformedURLException m){
}
try {
urlConnection = (HttpURLConnection) url.openConnection();
}catch (IOException e){}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}catch (IOException e){
} finally {
urlConnection.disconnect();
}
try {
JSONObject jsonObject = new JSONObject(result.toString());
JSONArray jsonArray = jsonObject.getJSONArray("rows");
JSONObject object_rows = jsonArray.getJSONObject(0);
JSONArray jsonArrayElements = object_rows.getJSONArray("elements");
JSONObject object_elements = jsonArrayElements.getJSONObject(0);
JSONObject object_duration = object_elements.getJSONObject("duration");
JSONObject object_distance = object_elements.getJSONObject("distance");
duration = object_duration.getString("text");
distance = object_distance.getString("text");
} catch (JSONException e) {
e.printStackTrace();
}
return distance + ", " + duration;
}
@Override
protected void onPostExecute(String result) {
mFragmentCallback.onTaskDone(result);
}
}
I'm trying to do this, but I only show the last marker of my list:
Call in the loop the method:
startRetrievenDistanceAndDuration();
And in onTaskDone try to put the marker, but only get the last marker of my list
@Override
public void onTaskDone(String result) {
mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(nameBeach)
.snippet(result)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
UPDATED AFTER CHANGES: (still don't work) I can parse the data in Asynctask and send it in onPostExecute, but I only get one value, and not the 9 values that I have....
MAIN ACTIVITY:
DistanceBetweenLocations task = new DistanceBetweenLocations(mlatituDouble, mlongitudeDouble){
@Override
protected void onPostExecute(HashMap<String, String> result) {
super.onPostExecute(result);
String name = result.get("beachName");
String distance = result.get("distance");
String duration = result.get("duration");
String latitue = result.get("latitude");
String longitude = result.get("longitude");
Double mlatituDouble = Double.parseDouble(latitue);
Double mlongitudeDouble = Double.parseDouble(longitude);
if (mMap == null) {
mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapView))
.getMap();
Toast.makeText(getActivity(), "mMap NO null", Toast.LENGTH_SHORT).show();
mMap.addMarker(new MarkerOptions().position(new LatLng(mlatituDouble, mlongitudeDouble))
.title(name)
.snippet(distance + " " + duration)
.icon(BitmapDescriptorFactory.defaultMarker()));
}
}
};
task.execute();
ASYNCTASK CLASS:.
public class DistanceBetweenLocations extends AsyncTask<String, String, HashMap<String, String>> {
Double currentLatitude;
Double currentlongitude;
public BeachMap beachMap;
public BackendlessCollection<Beach> dataBeach;
public GoogleMap mMap;
String latitude;
String longitude;
HashMap<String, String> map;
public DistanceBetweenLocations(Double currentLatitude, Double currentlongitude){
this.currentLatitude = currentLatitude;
this.currentlongitude = currentlongitude;
}
@Override
protected HashMap<String, String> doInBackground(String... params) {
dataBeach = beachMap.listBeach;
for (Beach city : dataBeach.getData()) {
GeoPoint geoPoint = city.getLocation();
String nameBeach = city.getName();
if (geoPoint == null) {
} else {
latitude = String.valueOf(geoPoint.getLatitude());
longitude = String.valueOf(geoPoint.getLongitude());
HttpURLConnection urlConnection = null;
URL url = null;
StringBuilder result = null;
String duration = "";
String distance = "";
try {
url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxxx");
} catch (MalformedURLException m) {
}
try {
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
} catch (IOException e) {
} finally {
urlConnection.disconnect();
}
try {
JSONObject jsonObject = new JSONObject(result.toString());
JSONArray jsonArray = jsonObject.getJSONArray("rows");
JSONObject object_rows = jsonArray.getJSONObject(0);
JSONArray jsonArrayElements = object_rows.getJSONArray("elements");
JSONObject object_elements = jsonArrayElements.getJSONObject(0);
JSONObject object_duration = object_elements.getJSONObject("duration");
JSONObject object_distance = object_elements.getJSONObject("distance");
duration = object_duration.getString("text");
distance = object_distance.getString("text");
map = new HashMap<String, String>();
map.put("beachName", nameBeach);
map.put("distance", distance);
map.put("duration", duration);
map.put("latitude", latitude);
map.put("longitude", longitude);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
return map;
}
}
I'll use your last code (the "UPDATED AFTER CHANGES"), ok?
If I get it right, your DistanceBetweenLocations result will be a list of beaches geolocation data. So, on every iteration of the for loop in doInBackground, you are replacing the value of "map" variable, this is your problem.
To solve your problem, you can have a List of HashMap or a List of a Pojo like this:
Using the Pojo, your AsyncTask will be like this:
Now you have a List to iterate. I have adjusted the code a little bit to this goal:
I hope you understand the idea of returning a List from your AsyncTask and loop throught the result on onPostExecute method.
Note: this is an implementation without knowing the real code, then you should adjust to your reality.
I'm not exactly sure what you're trying to do but I think you've made this more complicated then it has to be.
From what I understand you have a list of
City
objects and you use them to construct some URLs from which you retrieve aJSON
object that is use to constructMarkerOptions
objects.You can do that using a
AsyncTask
like this:And here is how you can use this task.
The idea is that you need to execute all the long running operation in the
AsyncTask
'sdoInBackground(...)
method. Also, you don't need to create other objects to deal with theAsyncTask
response, you can override the task'sonPostExecute(...)
inside the class you've created the task in.