javaandroidlocationreorderlist

How can I display my list (RecyclerView) in order of the most user's location?


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?

As in this picture : The image illustrates what I want to achieve

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


Solution

  • 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