I'm working on an activity where users are allowed to filter their search results. Initially, I fetch all data but when the user wants to filter it, I need to call another query and update the view. I am using Android ROOM and ViewModel for this.
The problem is that each time I fetch new data I need to create a new observer as the old one "stops" firing up. Normally, this should work with one observer, which would be called every time data is updated. Can you help me understand why this is happening, please?
Activity:
package com.jds.fitnessjunkiess.getfitapp.Activities.ExercisesView;
import android.arch.lifecycle.ViewModelProviders;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import com.jds.fitnessjunkiess.getfitapp.Activities.ExercisesView.Adapters.ExercisesAdapter;
import com.jds.fitnessjunkiess.getfitapp.Data.ViewModels.ExerciseViewModel;
import com.jds.fitnessjunkiess.getfitapp.R;
public class ExercisesViewActivity extends AppCompatActivity implements View.OnClickListener {
private ExerciseViewModel exerciseViewModel;
private ExercisesAdapter recyclerViewerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercises_view);
Toolbar toolbar = findViewById(R.id.toolbar_exercise_view_activity);
toolbar.setTitle("Exercises");
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
}
RecyclerView recyclerView = findViewById(R.id.exercise_view_recycle_viewer);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
this.recyclerViewerAdapter = new ExercisesAdapter();
recyclerView.setAdapter(recyclerViewerAdapter);
this.exerciseViewModel = ViewModelProviders.of(this).get(ExerciseViewModel.class);
this.exerciseViewModel.setFilters("", "");
// this.exerciseViewModel.selectAll();
this.exerciseViewModel.select().observe(this, exercises -> {
if (exercises != null) {
this.recyclerViewerAdapter.updateDataset(exercises);
}
});
Button button = findViewById(R.id.test_button);
button.setOnClickListener(this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
}
return true;
}
@Override
public void onClick(View v) {
this.exerciseViewModel.setFilters("", "");
// this.exerciseViewModel.select().observe(this, exercises -> {
// if (exercises != null) {
// this.recyclerViewerAdapter.updateDataset(exercises);
// }
// });
}
}
View Model:
public class ExerciseViewModel extends AndroidViewModel {
ExercisesRepository repository;
LiveData<List<Exercise>> data;
public ExerciseViewModel(Application application) {
super(application);
this.repository = new ExercisesRepository(application);
}
public void setFilters(String muscleGroups, String type) {
this.data = this.repository.filterSelect(muscleGroups, type);
}
public LiveData<List<Exercise>> select() {
return data;
}
public void insert(Exercise exercise) {
this.repository.insert(exercise);
}
}
Repository
public class ExercisesRepository {
private ExerciseDao dao;
public ExercisesRepository(Application context) {
WorkoutRoomDatabase database = WorkoutRoomDatabase.getDb(context);
this.dao = database.exerciseDao();
}
public LiveData<List<Exercise>> filterSelect(String muscleGroups, String type) {
return this.dao.filterSelect("%" + muscleGroups + "%", "%" + type + "%");
}
public void insert(Exercise exercise) {
new insertAsyncTask(this.dao).execute(exercise);
}
private static class insertAsyncTask extends AsyncTask<Exercise, Void, Void> {
private ExerciseDao exerciseDao;
insertAsyncTask(ExerciseDao dao) {
exerciseDao = dao;
}
@Override
protected Void doInBackground(final Exercise... params) {
exerciseDao.insert(params[0]);
return null;
}
}
}
DAO:
@Dao
public interface ExerciseDao {
@Query("SELECT * FROM exercises WHERE muscleGroups LIKE :muscleGroup AND type LIKE :type")
LiveData<List<Exercise>> filterSelect(String muscleGroup, String type);
@Query("SELECT * FROM exercises")
LiveData<List<Exercise>> selectAll();
@Insert
void insert(Exercise exercise);
@Update
void update(Exercise exercise);
@Delete
void delete(Exercise exercise);
@Query("DELETE FROM exercises")
void deleteAll();
}