1

I successfully implemented my ListActivity with a ContextMenu with two MenuItems: "Move up" and "Move down". When clicked the code swaps column order_id between two objects.

MainActivity.java

@Override
public boolean onContextItemSelected(MenuItem item) {
  ...

  case CONTEXT_MENU_MOVE_UP:
    datasource.moveCommandUp(command);
    adapter.reOrder();
    adapter.notifyDataSetChanged();
    break;

  case CONTEXT_MENU_MOVE_DOWN:
    datasource.moveCommandDown(command);
    adapter.reOrder();
    adapter.notifyDataSetChanged();
    break;

  ...
}

CustomAdapter.java

public class CustomAdapter extends ArrayAdapter<Command>{

  ArrayList<Command> objects;

  ...

  public void reOrder() {
    Collections.sort(objects, new Comparator<Command>() {
      public int compare(Command c1, Command c2) {
          return c1.compareTo(c2);
        }
      });
  }
}

Command.java

public class Command  implements Comparable<Command> {
  public long id;
  public String name;
  public Long order_id;

  @Override
  public int compareTo(Command c) {
    return this.order_id.compareTo(c.order_id);
  }
}

I can see that datasource.moveCommandUp(command) and datasource.moveCommandDown(command) work well because if I close and restart my app, the list is ordered and the two objects are correctly swapped.

The problem is that I need to restart the app for the effect to be shown, right after clicking "Move up" or "Move down" no changes take place.

What is wrong?

Edit after Christian's answer

I wasn't updating my adapter's objects. Instead of using sort, I call getAllCommands(), this gives me the array in its new order (reason for which on restart items were ordered) and I reset objects with the new ones. Now the listview updates but if I click on one item.. I still get the previous one, i.e. it triggers the action provided by the former item. What's wrong?

MainActivity.java

@Override
public boolean onContextItemSelected(MenuItem item) {
  ...

case CONTEXT_MENU_MOVE_UP:
  datasource.moveCommandUp(command);

  values = datasource.getAllCommands();
  adapter.setObjects(values);
  break;

case CONTEXT_MENU_MOVE_DOWN:
  datasource.moveCommandDown(command);

  values = datasource.getAllCommands();
  adapter.setObjects(values);
  break;

  ...
}

CustomAdapter.java

public class CustomAdapter extends ArrayAdapter<Command>{

  ArrayList<Command> objects;

  ...

  public void setObjects(ArrayList<Command> newObjects) {
    objects = newObjects;
    notifyDataSetChanged();
  }
}

EDIT 2

Using

final Command command = adapter.getItem(position);

intead of

final Command command = (Command) getListAdapter().getItem(position);

solved the problem!

SchwarzeHuhn
  • 638
  • 5
  • 17

1 Answers1

1

Even if you have removed the part of your adapter where you set your objects array, it seems, that you are initializing your objects array with the contents of the database, in reorder() you sort your objects array, but you do not show any code, where the objects array is reloaded from the database. You could do this in your adapter before notifyDataSetChanged().

Christian
  • 4,596
  • 1
  • 26
  • 33
  • Right to the point. I was sorting the array without reloading the updated order_ids from the database. Now I reload objects from my database, updated and sorted, then reset my adapter's objects and the listview updates. But when clicking on one item it triggers the former's action – SchwarzeHuhn Sep 22 '15 at 17:12
  • you should post your full code, otherwise it is impossible to make guesses – Christian Sep 22 '15 at 23:07
  • You are right. In the meantime I managed to solve by using `getListAdapter().getItem(position);` instead of `adapter.getItem(position);` solved the problem. – SchwarzeHuhn Sep 23 '15 at 18:37