How can I display the list (RecyclerView) in the order of the most user’s location (one point), by calculating the distance of each item from the location and user? As you can see on my code, while browsing the json, I calculate the distance but each time the user changes position, the list increments with the same data
Note that: If the user's position changes, what must be done to update the list?
And here is my code :
private List<MarkerObj> markerObjList;
private void getStation() {
progressBar.setVisibility(View.VISIBLE);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, API_XOIL.STATIONS_LIST, null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
markerObjList = new ArrayList<>();
for (int i=0; i<response.length(); i++) {
try {
JSONObject jsonObject = response.getJSONObject(i);
MarkerObj markerObj = new MarkerObj(
jsonObject.getInt("id"),
jsonObject.getString("libele"),
jsonObject.getString("reference"),
jsonObject.getString("latitude"),
jsonObject.getString("longitude"),
jsonObject.getString("images"),
jsonObject.getString("alimentation"),
jsonObject.getString("wifi"),
jsonObject.getString("fastfood"),
jsonObject.getString("lavage"),
jsonObject.getString("entretien"));
/*markerObjList.add(markerObj);
NosStations.AdapterListeStations adapterListeStations = new NosStations.AdapterListeStations(getApplicationContext(), markerObjList);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), LinearLayoutManager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();*/
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
int finalI = i;
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latView = location.getLatitude();
double lonView = location.getLongitude();
try {
Location loc1 = new Location(markerObj.getName());
loc1.setLatitude(Double.parseDouble(markerObj.getLat()));
loc1.setLongitude(Double.parseDouble(markerObj.getLon()));
Location loc2 = new Location("");
loc2.setLatitude(latView);
loc2.setLongitude(lonView);
float distanceInMeters = loc1.distanceTo(loc2);
String distanceView = String.valueOf(distanceInMeters);
MarkerObj markerObj1 = new MarkerObj(
markerObj.getId(),
markerObj.getName(),
markerObj.getRef(),
markerObj.getLat(),
markerObj.getLon(),
markerObj.getImages(),
markerObj.getAlimentation(),
markerObj.getWifi(),
markerObj.getFastfood(),
markerObj.getLavage(),
markerObj.getEntretien(),
distanceView);
markerObjList.add(markerObj1);
NosStations.AdapterListeStations adapterListeStations = new NosStations.AdapterListeStations(getApplicationContext(), markerObjList);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), LinearLayoutManager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
catch (Exception e){
e.printStackTrace();
Log.e("error", e.toString());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
assert locationManager != null;
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 30000, 0, locationListener);
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (error instanceof NetworkError) {
progressBar.setVisibility(View.GONE);
getOfflineMarker();
Toast.makeText(getApplicationContext(), getString(R.string.volley_network_error), Toast.LENGTH_LONG).show();
}
else if (error instanceof ServerError) {
progressBar.setVisibility(View.GONE);
getOfflineMarker();
Toast.makeText(getApplicationContext(), getString(R.string.volley_server_error), Toast.LENGTH_LONG).show();
}
else if (error instanceof AuthFailureError) {
progressBar.setVisibility(View.GONE);
getOfflineMarker();
Toast.makeText(getApplicationContext(), getString(R.string.volley_authfail), Toast.LENGTH_LONG).show();
}
else if (error instanceof ParseError) {
progressBar.setVisibility(View.GONE);
getOfflineMarker();
Toast.makeText(getApplicationContext(), getString(R.string.volley_parse_error), Toast.LENGTH_LONG).show();
}
else if (error instanceof TimeoutError) {
progressBar.setVisibility(View.GONE);
getOfflineMarker();
Toast.makeText(getApplicationContext(), getString(R.string.volley_time_out_error), Toast.LENGTH_LONG).show();
}
}
});
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonArrayRequest);
}
You need to separate the population of markerObjList and location change listener. In 'onResponse' method only populate the markerObject list.
create the location change listener in separate method say onCreate of view and when location listener is triggered, recalculate the distances for all marker object, sort the list based on updated distance and set the sorted list to adapter. The code will look something like this
onCreate()
{
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
int finalI = i;
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latView = location.getLatitude();
double lonView = location.getLongitude();
try {
ArrayList<> newMarkerObjList = new ArrayList<>();
int i = 0;
// recalcualte distances of all marker and add them in new list
for( i =0; i < markerObjList.size()){
MarkerObj markerObj = markerObjList[i]
Location loc1 = new Location(markerObj.getName());
loc1.setLatitude(Double.parseDouble(markerObj.getLat()));
loc1.setLongitude(Double.parseDouble(markerObj.getLon()));
Location loc2 = new Location("");
loc2.setLatitude(latView);
loc2.setLongitude(lonView);
float distanceInMeters = loc1.distanceTo(loc2);
String distanceView = String.valueOf(distanceInMeters);
MarkerObj markerObj1 = new MarkerObj(
markerObj.getId(),
markerObj.getName(),
markerObj.getRef(),
markerObj.getLat(),
markerObj.getLon(),
markerObj.getImages(),
markerObj.getAlimentation(),
markerObj.getWifi(),
markerObj.getFastfood(),
markerObj.getLavage(),
markerObj.getEntretien(),
distanceInMeters,
distanceView);
newMarkerObjList.add(markerObj1);
}
// create a predicate for sorting based on 'distanceInMeters';
Collections.sort( newMarkerObjList);
markerObjList = newMarkerObjList;
// and set this new list to the adapter;
NosStations.AdapterListeStations adapterListeStations = new NosStations.AdapterListeStations(getApplicationContext(), markerObjList);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), LinearLayoutManager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
catch (Exception e){
e.printStackTrace();
Log.e("error", e.toString());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
}
Current location listener is added for each element in array and the a updated marker object is added in same list , hence resulting in duplicate markers in the list and increasing the size of marker list