Nicholas Muir
Nicholas Muir

Reputation: 3124

Updating the data (Arraylist) for recyclerview from a a swipe helper

I have a recyclerview that contains data for alarms:

I bring in the data in the main fragment on createview like this:

// Data
alarms = AlarmCollection.getAlarms(getActivity());

// Adapter
adapter = new AlarmsAdapter(getActivity(), alarms);
rv.setAdapter(adapter);

I also add a swipe helper to handle when a user swipes (discards) an alarm like this:

// Swipe helper
ItemTouchHelper.Callback callback = new SwipeHelper(adapter);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(rv);

And to update the data (arraylist) for the recycler view I have a function in the mainfragment for updating like this:

public void update(){
   alarms.clear();
   alarms.addAll(AlarmCollection.getAlarms(getActivity()));
   adapter.notifyDataSetChanged();
}

This update function works fine when being called from the main alarm fragment so I know the function is ok.

My problem is that function needs to be called from the swipe helper class as it is needed when the user swipes off an alarm:

I tried making the alarms array static that didn't work got a null pointer.

Then i tried calling the update function from the swipe helper like this:

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

    AlarmsFragment = new MainAlarmsFragment();
    adapter.dismissAlarm(viewHolder.getAdapterPosition());
    AlarmsFragment.update();

}

But again I get a null pointer exception.

How do I update the array and call notifydatasetchanged from the swipe helper class?

EDIT:

This is the swipe helper where the on swiped is overridden (it is in its own class file):

public class SwipeHelper extends ItemTouchHelper.SimpleCallback {

    AlarmsAdapter adapter;

    public SwipeHelper(int dragDirs, int swipeDirs) {
        super(dragDirs, swipeDirs);
    }

    public SwipeHelper(AlarmsAdapter adapter) {
        super(ItemTouchHelper.UP | ItemTouchHelper.DOWN,ItemTouchHelper.RIGHT |ItemTouchHelper.LEFT);
        this.adapter = adapter;
    }


    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

             adapter.dismissAlarm(viewHolder.getAdapterPosition());


    }
}

This is calling the dismiss function in the adapter but has no reference to the main alarm fragment where the Arraylist is created.

This is my current constructor for the adapter:

public class AlarmsAdapter extends RecyclerView.Adapter<AlarmHolder>{
    Context c;
    ArrayList <Alarm> alarms;

    ArrayList <Integer> alarmsIdsArray;

    public AlarmsAdapter(Context c, ArrayList<Alarm> alarms) {
        this.c = c;
        this.alarms = alarms;
    }

Thanks in advance for your help

Upvotes: 0

Views: 585

Answers (2)

EEJ
EEJ

Reputation: 678

Here is the updated solution based on the information provided

public class SwipeHelper extends ItemTouchHelper.SimpleCallback {
    AlarmsAdapter adapter;
    MainAlarmsFragment fragment;

public SwipeHelper(int dragDirs, int swipeDirs) {
    super(dragDirs, swipeDirs);
}

public SwipeHelper(MainAlarmsFragment fragment, AlarmsAdapter adapter) {
    super(ItemTouchHelper.UP | ItemTouchHelper.DOWN,ItemTouchHelper.RIGHT |ItemTouchHelper.LEFT);
    this.fragment = fragment;
    this.adapter = adapter;
}


@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    adapter.dismissAlarm(viewHolder.getAdapterPosition());
    fragment.update();
}
}

Added an extra Argument in the SwipeHelper class which will keep the reference of the Fragment which need to be update.

Now you will have to update the constructor of SwipeHelper in your MainFragment as well by passing the fragment reference

// Swipe helper
ItemTouchHelper.Callback callback = new SwipeHelper(this, adapter);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(rv);

With these two changes I hope your problem gets resolved.

Upvotes: 2

aelimill
aelimill

Reputation: 1015

You can make a reference to your fragment through some interface which can be bound to your SwipeHelper or Adapter directly.

for example

interface AlarmDismissListener {

    onAlarmDismissed(Alarm alarm); 
}

and your fragment should implement this interface

class AlarmsFragment extends Fragment implements AlarmDismissListener {

//your code

   public void onAlarmDismissed(Alarm alarm) {
      //your code

      update();
   }

}

changes for adapter

class AlarmAdapter extends RecyclerView.Adapter {

  // your code

  // new field for your listener
  AlarmDismissListener dismissListener;

  //setter
  public void setDismissListener(AlarmDismissListener dismissListener) {
    this.dismissListener = dismissListener;
  }


  //invoke the listener method in method 
  public void dismissAlarm(int position) {
      //your code

      dismissListener.onAlarmDismissed(alarms.get(position));
   }

}

After that you can set this interface to your adapter through constructor or setter.

// Adapter
adapter = new AlarmsAdapter(getActivity(), alarms);
adapter.setDismissListener(this);
rv.setAdapter(adapter);

Upvotes: 1

Related Questions