0

In my application I have a RecyclerView and the user is able to select different kinds of orderings for the items within it. The ordering is based on a Comparator.

Let's assume the user rotates the device: After the configuration change I want to restore the ordering of the items. I thought about doing it this way:

public interface ItemComparator<T> extends Comparator<T>, Serializable { }

public class TestActivity extends AppCompatActivity {
    private static final String KEY_COMP = "COMP";
    private ItemComparator<MyItem> comparator;

    protected void onCreate(@Nullable Bundle savedState) {
        // main setup

        if(savedState == null) {
            comparator = (a, b) -> a.getName().compareTo(b.getName());
        } else {
            // unsafe cast here - can I get rid of it?
            comparator = (ItemComparator<MyItem>) savedState.getSerializable(KEY_COMP);
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(KEY_COMP, comparator);
    }
}

Is this valid code or can this cause a memory leak or any other problems?

Cilenco
  • 6,951
  • 17
  • 72
  • 152

1 Answers1

2

To do this, you can make a Sorter comparator for every ordering. The class takes field and direction parameters to sort, which is the values you save to the bundle.

public class Sorter implements Comparator<Item> {

    public static final int SORT_BY_DATE = 0;
    public static final int SORT_BY_DESCRIPTION = 1;
    public static final int SORT_BY_AMOUNT = 2;

    public static final int SORT_DIR_ASCENDING = 1;
    public static final int SORT_DIR_DESCENDING = -1;

    private int field;
    private int direction;

    public Sorter(int field, int direction) {
        this.field = field;
        this.direction = direction;
    }

    public int getField() {
        return field;
    }

    public int getDirection() {
        return direction;
    }

    @Override
    public int compare(Item i1, Item i2) {
        int order = 0;

        switch (field) {
            case SORT_BY_DATE:
                order = Long.compare(i1.date, i2.date);
                break;

            case SORT_BY_DESCRIPTION:
                order = i1.description.compareTo(i2.description)
                break;

            case SORT_BY_AMOUNT:
                order = Integer.compare(i1.amount, i2.amount)
                break;
        }

        return order * direction;
    }

}

In onCreate():

if (savedState == null) {
    // Default parameters
    comparator = new Sorter(Sorter.SORT_BY_DATE, Sorter.SORT_DIR_ASCENDING);
} else {
    int field = bundle.getInt("comparatorField");
    int dir = bundle.getInt("comparatorDir");
    comparator = new Sorter(field, dir)
}

In onSaveInstanceState(Bundle savedState):

bundle.putInt("comparatorField", comparator.getField());
bundle.putInt("comparatorDir", comparator.getDirection());

Serialiazing the comparator is definitively not the way to go, in fact, you should avoid using that with Android in general.

Nicolas
  • 6,611
  • 3
  • 29
  • 73