Android LiveData Observer not being triggered second time

Android LiveData Observer not being triggered second time



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();




2 Answers
2



You need make some changes because you are reassigning the LiveData object instead of add the items filtered.



You need chante your LiveData> data as MutableLiveData> and in the setFilters method you need get the arraylist from the repository and add it in the MutableLiveData using the setValue method.



ExerciseViewModel


MutableLiveData<List<Exercise>> data = new MutableLiveData<>();


public void setFilters(String muscleGroups, String type)
List<Exercise> ex = this.repository.filterSelect(muscleGroups, type).getValue();
this.data.setValue(ex);



I hope it helps you.





Thanks for to code example. I have implemented this change but now results from DB are always NULL but I know there is data in DB matching that query.
– Jeremi
Sep 2 at 9:15





I forgot create the instance of MutableLiveData: MutableLiveData<List<Exercise>> data = new MutableLiveData<>();
– Juanjo Berenguer
Sep 2 at 9:17





I've created an instance of MutableLiveData in the ViewModel. However, it is the result of DAO that returns LiveData on which I call getValue() and get NULL.
– Jeremi
Sep 2 at 9:25





So, then you need to check and debug your code. Maybe you have something else. I can't test the whole code. Sorry
– Juanjo Berenguer
Sep 2 at 9:46





Anyway i am looking your code and you are missing things, Where is your recyclerView declared? Where are you setting the adapter to recyclerview.setAdapter()
– Juanjo Berenguer
Sep 2 at 9:50



In your setFilters method, you are reassigning a whole new live data to the live data instance you have. Live data only fires event when it's value get changed. So instead you can use a mutable live data, and set it's value by setValue() of this class. And your observer will be called.





Thank you! I will try it now and let you know if it worked. :)
– Jeremi
Sep 2 at 8:37



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)