0

I'm trying to figure out how to sort my recyclerview's data by click of a button. So far I've got it sorted initially as I start the application and add new items on the list. But I'd like to be able to sort it by different parameters as I'm using the app, by clicking a button "Sort by distance". I'm using the MVVM architecture and am working with LiveData.

Here's my MainActivity (Not completely, but irrelevant parts are omitted)

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView recyclerView = findViewById(R.id.recyclerview);
        final RunListAdapter adapter = new RunListAdapter(new RunListAdapter.RunDiff());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        mRunViewModel = new ViewModelProvider(this).get(RunViewModel.class);
        mRunViewModel.getAllRuns().observe(this, runs -> {
            adapter.submitList(runs);
        });

 sortByDistanceButton = findViewById(R.id.sortByDistance);
        sortByDistanceButton.setOnClickListener(view -> {
             //DO SOMETHING
        });

Here's my RunViewModel

public class RunViewModel extends AndroidViewModel {

    private RunRepository mRepository;
    private final LiveData<List<Run>> mAllRuns;


    public RunViewModel(Application application) {
        super(application);
        mRepository = new RunRepository(application);
        mAllRuns = mRepository.getAllRuns();
    }

    LiveData<List<Run>> getAllRuns() {
            return mRepository.getAllRuns();
    }

    public void insert(Run run) {
        mRepository.insert(run);
    }

    public void delete(Run run) {
        mRepository.delete(run);
    }

}

Here's my RunRepository

public class RunRepository {

    private RunDao mRunDao;
    private LiveData<List<Run>> mAllRuns;

    RunRepository(Application application) {
        RunRoomDatabase db = RunRoomDatabase.getDatabase(application);
        mRunDao = db.runDao();
        mAllRuns = mRunDao.getRunsByDate();
    }

    LiveData<List<Run>> getAllRuns() {
        return mRunDao.getRunsByDate();
    }


    void insert(Run run) {
        RunRoomDatabase.databaseWriteExecutor.execute(() ->
                mRunDao.insert(run));
    }

    public void delete(Run run) {
        RunRoomDatabase.databaseWriteExecutor.execute(() -> {
            mRunDao.deleteRun(run);
        });
    }

}

And finally here's my RunDao

public interface RunDao {

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    void insert(Run run);

    @Query("DELETE FROM run_table")
    void deleteAll();

    @Query("SELECT * FROM run_table ORDER BY date")
    LiveData<List<Run>> getRunsByDate();

    @Query("SELECT * FROM run_table ORDER BY distance ASC")
    LiveData<List<Run>> getRunsByDistance();

    @Query("SELECT * FROM run_table ORDER BY duration ASC")
    LiveData<List<Run>> getRunsByDuration();
    @Delete
    void deleteRun(Run run);
}

I've tried to pass on a "choice" argument and setting the choice to a different one, but to no avail. I've tried to read about other's having similar problems, but I haven't been able to figure how to apply any of them to my situation. I'm completely stumped.

Here are some SO questions I've read and tried to wrap my head around. This one actually is very similar to mine and the original question asked figured out a solution, but never shared the details of the implementation =) How to sort LiveData from Room Database? Doing a button to switch recyclerview's item's order

https://www.reddit.com/r/androiddev/comments/n9nraa/i_want_to_sort_a_livedatalistplayers_from_room_in/

how to properly sort a list using repository pattern and live data in an MVVM android application?

Apelli
  • 25
  • 6

1 Answers1

1

Moving from top to bottom,

  1. You are observing mRunViewModel.getAllRuns()
  2. Your mRunViewModel.getAllRuns() is mRepository.getAllRuns();
  3. Your mRepository.getAllRuns(); is mRunDao.getRunsByDate();

So you are so far just unconditionally routing LiveData from Room to your view.

Simplest way to achieve switching could be this:

  1. Change your RunDao to have single parameterized method like this example
@Query("SELECT * FROM Persons ORDER BY 
        CASE WHEN :isAsc = 1 THEN first_name END ASC, 
        CASE WHEN :isAsc = 0 THEN first_name END DESC")
List<Person> getPersonsAlphabetically(boolean isAsc);

(your implementation will be different, including return type and parameter type, but the above should give the idea)

  1. Route the above dao method into repo and use updated repo inside vm. Every time view decides it's time to show some different sorting order, it will talk to view model, viewmodel will pull repo's method and repo will pull dao with proper parameter, dao will give you back livedata with properly sorted content.
ror
  • 3,295
  • 1
  • 19
  • 27