Перерисовка маркеров google maps api

188
05 октября 2018, 02:20

Имеется класс, реализующий поиск ближайших мест на карте путем отправки запроса и получения результатов в json. Запросы отправляются и получаются в отдельном потоке с небольшим интервалом (не обращайте внимание на кривую оптимизацию кода, это тестовый вариант). Проблема в том, что после получения новых результатов, в зависимости от местоположения пользователя, маркеры на карте не перерисовываются. Рассчитывал, что они смогут перерисовываться в отдельном потоке, но не особо получается это реализовать в данном классе. Как можно выкрутиться из этой ситуации? Очень нужно, чтобы маркеры перерисовывались после получения нового результата запроса. Ниже прилагается код класса:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
    GoogleMap.OnMyLocationButtonClickListener,
    GoogleMap.OnMyLocationClickListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private Location placeLocation;
private Marker mLocationMarker;
Thread thread, thread1;
double mLat, mLng;
double placeLat, placeLng;
int radius = 300;
boolean firstRun = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mSupportMapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mSupportMapFragment.getMapAsync(this);
}
@Override
protected void onPause() {
    super.onPause();
    if (mGoogleApiClient != null) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
}
/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    // Add a marker in Sydney and move the camera
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    mMap.setMyLocationEnabled(true);
    mMap.setOnMyLocationButtonClickListener(this);
    mMap.setOnMyLocationClickListener(this);
    //Initialize Google Play Services
    buildGoogleApiClient();
    mGoogleApiClient.connect();
}
public StringBuilder stringBuilderMethod(Location mLocation) {
    //current location
    double mLatitude = mLocation.getLatitude();
    double mLongitude = mLocation.getLongitude();
    StringBuilder stringBuilder = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
    stringBuilder.append("location=").append(mLatitude).append(",").append(mLongitude);
    stringBuilder.append("&keyword=пятерочка | магнит");
    stringBuilder.append("&language=ru");
    stringBuilder.append("&radius=").append(radius);
    stringBuilder.append("&sensor=true");
    stringBuilder.append("&key=********************************");
    Log.d("Map", "<><>api: " + stringBuilder.toString());
    return stringBuilder;
}
protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}
@Override
public boolean onMyLocationButtonClick() {
    Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show();
    // Return false so that we don't consume the event and the default behavior still occurs
    // (the camera animates to the user's current position).
    return false;
}
@Override
public void onMyLocationClick(@NonNull Location location) {
    Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG).show();
    this.mLocation = location;
    Intent intent = new Intent(MapsActivity.this, StartActivity.class);
    intent.putExtra("loc", this.mLocation.toString());
    setResult(RESULT_OK, intent);
}
@Override
public void onConnected(Bundle bundle) {
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(final Location location) {
    mLocation = location;
    if (mLocationMarker != null) {
        mLocationMarker.remove();
    }
    mLat = location.getLatitude();
    mLng = location.getLongitude();
    mLocation.setLatitude(mLat);
    mLocation.setLongitude(mLng);
    //Place current location marker
    LatLng latLng = new LatLng(mLat, mLng);
    Circle circle = mMap.addCircle(new CircleOptions()
            .center(latLng)
            .radius(radius).strokeColor(Color.argb(50, 255, 0, 0))
            .fillColor(Color.argb(100, 255, 0, 0)));
//        MarkerOptions markerOptions = new MarkerOptions();
//        markerOptions.position(latLng);
//        markerOptions.title("Position");
//        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
//        mLocationMarker = mMap.addMarker(markerOptions);
    //Move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(10));
    thread = new Thread() {
        @Override
        public void run() {
            while (true) {
                //Query places with current location
                StringBuilder stringBuilderValue = new StringBuilder(stringBuilderMethod(location));
                PlacesTask placesTask = new PlacesTask();
                placesTask.execute(stringBuilderValue.toString());
                try {
                    Thread.sleep(15000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    thread.start();
    if (mGoogleApiClient != null) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
}
private class PlacesTask extends AsyncTask<String, Integer, String> {
    String result;
    String data = null;
    // Invoked by execute() method of this object
    @Override
    protected String doInBackground(String... url) {
        try {
            data = downloadUrl(url[0]);
        } catch (IOException e) {
            Log.d("Background Task", e.toString());
        }
        return data;
    }
    // Executed after the complete execution of doInBackground() method
    @Override
    protected void onPostExecute(final String result) {
        this.result = result;
        thread1 = new Thread(){
            @Override
            public void run() {
                while (true){
                    Log.d("results", "<><> result: " + result);
                    ParserTask parserTask = new ParserTask();
                    // Start parsing the Google places in JSON format
                    // Invokes the "doInBackground()" method of the class ParserTask
                    parserTask.execute(result);
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread1.start();
    }
}
private String downloadUrl(String strUrl) throws IOException{
    String data = "";
    InputStream inputStream = null;
    HttpURLConnection urlConnection = null;
    try {
        URL url = new URL(strUrl);
        // Creating an http connection to communicate with url
        urlConnection = (HttpURLConnection) url.openConnection();
        // Connecting to url
        urlConnection.connect();
        // Reading data from url
        inputStream = urlConnection.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line);
        }
        data = stringBuilder.toString();
        bufferedReader.close();
    } catch (Exception e) {
        Log.d("Exception", e.toString());
    } finally {
        inputStream.close();
        urlConnection.disconnect();
    }
    return data;
}
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {
    JSONObject jsonObject;
    // Invoked by execute() method of this object
    @Override
    protected List<HashMap<String, String>> doInBackground(String... jsonData) {
        List<HashMap<String, String>> places = null;
        PlaceJSON placeJSON = new PlaceJSON();
        try {
            jsonObject = new JSONObject(jsonData[0]);
            places = placeJSON.parse(jsonObject);
        } catch (JSONException e) {
            Log.d("Exception", e.toString());
        }
        return places;
    }
    @Override
    protected void onPostExecute(List<HashMap<String, String>> list) {
        placeLocation = new Location("point B");
        Log.d("Map", "list size: " + list.size());
        // Clears all the existing markers;
        if (!firstRun) {
            mMap.clear();
        }
        firstRun = false;
        for (int i = 0; i < list.size(); i++) {
            //Creating a market
            MarkerOptions markerOptions = new MarkerOptions();
            //Getting a place from the Places list
            HashMap<String, String> hashMapPlace = list.get(i);
            //Getting Latitude of the place
            placeLat = Double.parseDouble(hashMapPlace.get("lat"));
            //Getting longitude of the place
            placeLng = Double.parseDouble(hashMapPlace.get("lng"));
            //Getting name
            String name = hashMapPlace.get("place_name");
            Log.d("Map", "place name: " + name);
            //Getting vicinity
            String vicinity = hashMapPlace.get("vicinity");
            LatLng latLng = new LatLng(placeLat, placeLng);
            placeLocation.setLatitude(placeLat);
            placeLocation.setLongitude(placeLng);
            double distance = mLocation.distanceTo(placeLocation);
            //Setting the position for the market
            markerOptions.position(latLng);
            BigDecimal bd = new BigDecimal(distance).setScale(1, RoundingMode.HALF_EVEN);
            distance = bd.doubleValue();
            if (distance < radius) {
                markerOptions.title(name + " : " + distance + " метров");
                markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE));
                //Placed a marker on the touched position
                mMap.addMarker(markerOptions);
            }
        }
    }
}
public class PlaceJSON {
    /*
      Receives a JSONObject and returns a list
     */
    public List<HashMap<String, String>> parse(JSONObject jsonObject) {
        JSONArray jsonArrayPlaces = null;
        try {
            jsonArrayPlaces = jsonObject.getJSONArray("results");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return getPlaces(jsonArrayPlaces);
    }
    private List<HashMap<String, String>> getPlaces(JSONArray jsonPlaces) {
        int placesCount = jsonPlaces.length();
        List<HashMap<String, String>> placesList = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> place = null;
        /* Taking each place, parses and adds to list object */
        for (int i = 0; i < placesCount; i++) {
            try {
                /* Call getPlace with place JSON object to parse the place */
                place = getPlace((JSONObject) jsonPlaces.get(i));
                placesList.add(place);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return placesList;
    }
    /*
     * Parsing the Place JSON object
     */
    private HashMap<String, String> getPlace(JSONObject jsonPlace) {
        HashMap<String, String> place = new HashMap<String, String>();
        String placeName = "-RU-";
        String vicinity = "-RU-";
        String latitude = "";
        String longitude = "";
        String reference = "";
        try {
            // Extracting Place name, if available
            if (!jsonPlace.isNull("name")) {
                placeName = jsonPlace.getString("name");
            }
            // Extracting Place Vicinity, if available
            if (!jsonPlace.isNull("vicinity")) {
                vicinity = jsonPlace.getString("vicinity");
            }
            latitude = jsonPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
            longitude = jsonPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");
            reference = jsonPlace.getString("reference");
            place.put("place_name", placeName);
            place.put("vicinity", vicinity);
            place.put("lat", latitude);
            place.put("lng", longitude);
            place.put("reference", reference);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return place;
    }
}

}

Буду благодарен за любую помощь! Ниже прилагаются скриншот работы приложения на данный момент:

READ ALSO
Retrofit2 Android Java

Retrofit2 Android Java

ЗдраствуйтеНе как не могу вникнуть как отправлять изоброжения на сервер с помощью retrofit2

155
Лямбда-выражения в Java [дубликат]

Лямбда-выражения в Java [дубликат]

На данный вопрос уже ответили:

168
Где view из mvc в андроид приложении. Document-view. МVP.

Где view из mvc в андроид приложении. Document-view. МVP.

Возьмем просто андроид приложение : класс наследующий Activity в этом классе подключается layout и подписываемся на события от кнопокИ по определенному...

169