9

I'm trying to re-order my items list (Using android getListView, not custom) by distance and I'm having issues.

I'm getting the Spherical distance in meters (double) using Maps Utils inside the adapter ( SomeAdapter ).

double distance = SphericalUtil.computeDistanceBetween(fromCoord, toCoord);

But after I fill the adapter (AsyncTask) I need to short by distance on my onPostExecute and I have no idea.

    @Override
    protected void onPostExecute(Boolean result) {
        try {
            SQLiteHelper dbHelper = new SQLiteHelper(getActivity());
            pds = new SomeDataSource(dbHelper.db);

            ArrayList<Raids> some = pds.getAllRaids();

            SomeAdapter listViewAdapter = new SomeAdapter(getActivity(), some);
            getListView().setAdapter(listViewAdapter);

            SharedPreferences somename = context.getSharedPreferences("SomeName", Context.MODE_PRIVATE);
            Boolean UserOrder = somename.getBoolean("UserOrder", false);
            if (UserOrder){

            }

        } catch (SQLiteException | NullPointerException s) {
            Log.d("SomeName", "SomeFrag:", s);
        }
    }

Thank you

FilipeOS
  • 801
  • 1
  • 11
  • 42

2 Answers2

7

Just implement the Comparable interface in your Raids class -

class Raids implements Comparable<Raids> {
    private double distance;
    ...

    @Override
    public int compareTo(Raids instance2) {
        if (this.distance < instance2.distance)
            return -1;
        else if (this.distance > instance2.distance)
            return 1;
        else
            return 0;
    }
}

Then call Collections.sort on it -

ArrayList<Raids> some = pds.getAllRaids();
Collections.sort(some);

And update the adapter -

listViewAdapter.notifyDataSetChanged();
jL4
  • 1,238
  • 10
  • 15
  • Hi, the distance is calculated inside the Adapter because I fetch the actual coordinates and the new ones (current item) and convert to meters (double). Why you are placing it inside the Raids class? how can the class know that is the correct distance of that item? – FilipeOS Sep 14 '17 at 10:18
  • Also the Double is not saved on database, I use it only to calculate inside the Adapter and print. – FilipeOS Sep 14 '17 at 10:35
  • @FilipeOS I assumed `distance` was a field of the `Raids` class. If it is not, then the sorting is not possible as it requires a member of the class to perform the sort on. Can you explain more clearly what you are doing? – jL4 Sep 14 '17 at 12:55
  • I get the coordinates from server, save on sqllite, fill the adapter and on each item I calculate the spherical distance (meters / double) of my coordinates to the ones that are saved on sqllite (1 per list item ). I want to short the list by distance and I can only check this inside the adapter, after filled I guess. Please advise – FilipeOS Sep 14 '17 at 15:40
  • @FilipeOS You need a property of a class to sort a list of items of that class based upon that property. So the `Raids` class should contain a field `distance` imo. You should then calculate and update each object's `distance` after fetching the data and then the adapter can simply call for the list of objects and perform a sort on it using the comparator before filling. You need to refactor the code a bit, I think. – jL4 Sep 15 '17 at 05:46
  • Thank you. How can I save the distance of that specific item inside my adapter? So that it saves on the correct one? It can't be when I fetch and save because I calculate each time user goes to that fragment again (current vs saved location) – FilipeOS Sep 15 '17 at 08:33
  • @FilipeOS It's hard to tell without knowing the existing code but you should be able to fetch the data, loop over each object and pass the new value to a method of the class so that it can calculate and set the `distance` field of each object. Then get the list in the adapter and sort. The updation should be done before the fragment is loaded because you can't update and sort while the adapter is loading. – jL4 Sep 15 '17 at 10:03
  • Thank you. For what I can see I only can compare if I only save/read my location (compare and save double) in my server "fetch" otherwise I cannot "tell the app" that my actual distance is related to X item :) – FilipeOS Sep 15 '17 at 12:36
1

Given your code:

ArrayList<Raids> some = pds.getAllRaids();
SomeAdapter listViewAdapter = new SomeAdapter(getActivity(), some);

You need:

class SomeAdapter ... {

    private ArrayList<Raids> mData;

    //TODO: now call this method instead of computeDistanceBetween directly
    private void calculateForitem(Raids item) {
        double distance = SphericalUtil.computeDistanceBetween(item.fromCoord, item.toCoord);
        item.setDistance(distance);
        Collections.sort(mData); //the list inside adapter
        notifyDataSetChanged();
    }

}

and

class Raids implements Comparable<Raids> {

    private double distance;
     ...

    @Override
    public int compareTo(Raids instance2) {
        return (this.distance < instance2.distance)? -1 : (this.distance > instance2.distance)? 1 : 0;
    }

}
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124