0

Ich verwende Google Maps, um einige Markierungen anzuzeigen. Die Marker werden von einer Datenbank heruntergeladen und gleichzeitig bekomme ich die Distanzmatrix von Google API, zwischen der aktuellen Position des Benutzers und dem Marker, den ich von der Datenbank bekomme.Meine UI ist mit AsyncTask mit Entfernungsmatrix und Google Maps blockiert

Mein Problem ist, dass ich dies mit .get tun, mein ui bloking (ich habe gelesen, dass .get die ui blockiert:

dataFromAsyncTask = testAsyncTask.get(); 

Nun, ich versuche, das gleiche zu tun, ohne zu blockieren die ui, aber ich bin nicht in der gleichen Zeit erhalten werden kann, oder in einem guten Weg, der Abstand zu diesem Marker.

ich etwas Hilfe schätzen, bitte.

Dies ist mein Code mit meinem alt und falsch .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 Methode:

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 Klasse:

 @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); 
     } 
} 

Ich versuche, dies zu tun, aber ich zeige nur die letzte Markierung auf meiner Liste:

Anruf in die Schleife die Methode:

startRetrievenDistanceAndDuration(); 

Und in onTaskDone versuchen, den Marker zu setzen, aber nur die letzte Markierung auf meiner Liste

@Override 
      public void onTaskDone(String result) { 
       mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude())) 
         .title(nameBeach) 
         .snippet(result) 
         .icon(BitmapDescriptorFactory.defaultMarker())); 

      } 

AKTUALISIERT nach Änderungen erhalten: (nicht funktionieren noch) ich die Daten in AsyncTask analysieren kann und senden es in OnPostExecute, aber ich bekomme nur einen Wert, und nicht die 9 Werte, die ich habe ....

HAUPTTÄTIGKEIT:

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; 
    } 

} 

Antwort

1

Ich werde Ihren letzten Code verwenden (die " AKTUALISIERT NACH ÄNDERUNGEN "), ok?

Wenn ich es richtig mache, wird Ihr DistanceBetweenLocations Ergebnis eine Liste der Strände Geolocation Daten sein. Also, bei jeder Iteration der for-Schleife in doInBackground, ersetzen Sie den Wert von "map" Variable, das ist Ihr Problem.

public class BeachPojo { 
    private String beachName; 
    private String distance; 
    private String duration; 
    private String latitude; 
    private String longitude; 

    public String getBeachName() { 
     return beachName; 
    } 

    public void setBeachName(String beachName) { 
     this.beachName = beachName; 
    } 

    public String getDistance() { 
     return distance; 
    } 

    public void setDistance(String distance) { 
     this.distance = distance; 
    } 

    public String getDuration() { 
     return duration; 
    } 

    public void setDuration(String duration) { 
     this.duration = duration; 
    } 

    public String getLatitude() { 
     return latitude; 
    } 

    public void setLatitude(String latitude) { 
     this.latitude = latitude; 
    } 

    public String getLongitude() { 
     return longitude; 
    } 

    public void setLongitude(String longitude) { 
     this.longitude = longitude; 
    } 
} 

Mit dem Pojo, wird Ihr AsyncTask so aussehen::

Ihr Problem zu lösen, können Sie eine Liste der HashMap oder eine Liste eines Pojo wie diese haben können

public class DistanceBetweenLocations extends AsyncTask<String, String, List<BeachPojo>> { 

    Double currentLatitude; 
    Double currentlongitude; 
    public BeachMap beachMap; 
    public BackendlessCollection<Beach> dataBeach; 
    public GoogleMap mMap; 
    String latitude; 
    String longitude; 


    public DistanceBetweenLocations(Double currentLatitude, Double currentlongitude){ 
     this.currentLatitude = currentLatitude; 
     this.currentlongitude = currentlongitude; 
    } 

    @Override 
    protected List<BeachPojo> doInBackground(String... params) { 
     List<BeachPojo> list = new ArrayList<BeachPojo>(); 
     BeachPojo pojo; 

     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"); 

        pojo = new BeachPojo(); 
        pojo.setBeachName(nameBeach); 
        pojo.setDistance(distance); 
        pojo.setDuration(duration); 
        pojo.setLatitude(latitude); 
        pojo.setLongitude(longitude); 

        list.add(pojo); 

       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     return list; 
    } 
} 

Jetzt haben Sie eine Liste zu iterieren.

DistanceBetweenLocations task = new DistanceBetweenLocations(mlatituDouble, mlongitudeDouble){ 
    @Override 
    protected void onPostExecute(List<BeachPojo> result) { 
     super.onPostExecute(result); 

     if (mMap == null) { 
      mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapView)) 
        .getMap(); 
     } 

     Double beachLatitude; 
     Double beachLongitude; 

     for (BeachPojo pojo : result) { 
      beachLatitude = Double.parseDouble(pojo.getLatitude()); 
      beachLongitude = Double.parseDouble(pojo.getLongitude()); 

      mMap.addMarker(new MarkerOptions().position(new LatLng(beachLatitude, beachLongitude)) 
       .title(pojo.getBeachName()) 
       .snippet(pojo.getDistance() + " " + pojo.getDuration()) 
       .icon(BitmapDescriptorFactory.defaultMarker())); 
     } 
    } 
}; 

task.execute(); 

Ich hoffe, dass Sie die Idee verstehen auf OnPostExecute Methode eine Liste von Ihrem AsyncTask und Schleife throught das Ergebnis der Rückkehr: Ich habe den Code ein wenig zu diesem Ziel angepasst.

Hinweis: dies ist eine Implementierung ohne den echten Code zu kennen, dann sollten Sie auf Ihre Realität anzupassen.

0

Ich bin mir nicht ganz sicher, was Sie zu tun versuchen, aber ich denke, Sie haben das komplizierter gemacht, als es sein muss.

Von dem, was ich verstehen Sie haben eine Liste von City Objekte und verwenden Sie sie einige URLs zu konstruieren, aus dem Sie ein JSON Objekt abzurufen, die MarkerOptions Objekte Verwendung zu konstruieren ist.

können Sie tun, dass eine AsyncTask wie folgt aus:

public class Task extends AsyncTask<City, Void, Markers> { 

    String currentLatitude; 
    String currentlongitude; 

    public Task(String currentLatitude, String currentlongitude){ 
     this.currentLatitude = currentLatitude; 
     this.currentlongitude = currentlongitude; 
    } 

    @Override 
    protected String doInBackground(City... cities) { 
     final Markers mMap = ...; 
     for (City city : cities) { 
      GeoPoint geoPoint = city.getLocation(); 
      String nameBeach = city.getName(); 

      if (geoPoint != null) { 
       String latitude = String.valueOf(geoPoint.getLatitude()); 
       String longitude = String.valueOf(geoPoint.getLongitude()); 

       HttpURLConnection urlConnection = null; 
       BufferedReader reader = null; 
       try { 
        URL url = new URL("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + currentLatitude + "," + currentlongitude + "&destinations=" + latitude + "," + longitude + "&key=xxx";); 
        urlConnection = (HttpURLConnection) url.openConnection(); 
        reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); 
        StringBuilder result = new StringBuilder(); 
        String line; 
        while ((line = reader.readLine()) != null) { 
         result.append(line); 
        } 
        JSONObject jsonObject = new JSONObject(result.toString()).getJSONArray("rows").getJSONObject(0).getJSONArray("elements").getJSONObject(0); 
        String duration = jsonObject.getJSONObject("duration").getString("text"); 
        String distance = jsonObject.getJSONObject("distance").getString("text"); 

        mMap.addMarker(new MarkerOptions().position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude())) 
          .title(nameBeach) 
          .snippet(distance + ", " + duration) 
          .icon(BitmapDescriptorFactory.defaultMarker())); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } finally { 
        if(reader!=null){ 
         try { 
          reader.close(); 
         }catch (Exception e){ 
          e.printStackTrace(); 
         } 
        } 
        if (urlConnection != null) { 
         try { 
          urlConnection.disconnect(); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 

     return mMap; 
    } 
} 

Und hier ist, wie Sie diese Aufgabe verwenden können.

public class Login extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(...); 
     Task task = new Task(currentLatitude, currentlongitude){ 
      @Override 
      protected void onPostExecute(Markers markers) { 
       super.onPostExecute(markers); 
       //This runs on the UI thread and "markers" is the "mMap" object that was create on the background thread. 
      } 
     }; 
     List<City> cities = .... 
     task.execute(cities.toArray(new City[cities.size()])); 
    } 
} 

Die Idee ist, dass Sie alle lange laufenden Betrieb in der AsyncTask ‚s doInBackground(...) Methode ausführen müssen.Auch brauchen Sie nicht andere Objekte erstellen mit der AsyncTask Antwort umgehen, können Sie die Aufgabe der onPostExecute(...) innerhalb der Klasse überschreiben Sie die Aufgabe in erstellt haben.

+0

Danke für Ihre Antwort. Hab Sinn! Aber ich habe ein Problem mit Ihrem Code. Kann die Asynctask-Klasse ein GoogleMap-Objekt zurückgeben (um eine Markierung hinzuzufügen, die ich brauche, um ein Gmap-Objekt zu erzeugen) bekomme ich diesen Fehler bei der Rückkehr von doinbackground: erforderlich 'String' gegründet 'com.android ... GoogleMap'. Gleiches Problem in super.onPostExecute (markers); Danke – Simpson

+0

Eine Frage mehr, innerhalb von onPostExecute (GoogleMaps Marker) muss ich keinen Code mehr hinzufügen? Wird angenommen, dass wenn die Aufgabe diese Methode beendet, der Marker in die Karte gesetzt wird? – Simpson

+0

@Simpson Ich denke, dass das erste Problem, das Sie erwähnt haben, verursacht wird, weil Sie die Klasse nicht als öffentliche Klasse deklariert haben. Task extends AsyncTask ', wahrscheinlich haben Sie die öffentliche Klasse Task extends AsyncTask verwendet String, Void, String> '. – Titus