Android LiveData和Room:getValue返回NULL

Android LiveData和Room:getValue返回NULL,android,architecture,Android,Architecture,当使用ROOM从DB读取数据并返回LiveData时,getValue()方法返回null。一段时间以来,我一直无法理解到底出了什么问题。你能帮我解决这个问题吗?数据库中有数据,这似乎更像是我如何使用LiveData对象的问题 活动: public class ExercisesViewActivity extends AppCompatActivity implements View.OnClickListener { private ExerciseViewModel exercise

当使用ROOM从DB读取数据并返回LiveData时,getValue()方法返回null。一段时间以来,我一直无法理解到底出了什么问题。你能帮我解决这个问题吗?数据库中有数据,这似乎更像是我如何使用LiveData对象的问题

活动:

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);
//      }
//    });
  }
}
视图模型:

public class ExerciseViewModel extends AndroidViewModel {
  ExercisesRepository repository;
  MutableLiveData<List<Exercise>> data;

  public ExerciseViewModel(Application application) {
    super(application);
    this.data = new MutableLiveData<>();
    this.repository = new ExercisesRepository(application);
  }

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

  public void selectAll() {
//    this.data.setValue(this.repository.selectAll().getValue());
  }

  public LiveData<List<Exercise>> select() {
    return data;
  }

  public void insert(Exercise exercise) {
    this.repository.insert(exercise);
  }
}

这显然是正确的方法://

您试图在filterSelete中使用空值获取类似的搜索<代码>this.exerciseViewModel.setFilters(“,”)。 这个过滤器基本上是个问题。你不能像搜索一样空。 安装此功能后,您可以使用
loadAll
query

@Query(“从练习中选择*)
LiveData loadAll()

编辑:

public LiveData filterSelect(字符串musclegroup,字符串类型){
如果(肌肉群==“”&类型=“”){
返回这个.dao.loadAll()
}否则{
返回此.dao.filterSelect(“%”+muscleGroups+“%”,“%”+type+“%”);
}

希望它能解决您的问题。

您应该查看MediaLiveData,而不是MutableLiveData,它将允许您从存储库中提出更改

这类似于下面,您将存储库数据作为数据源添加到mediatorLiveData。然后,当您从存储库接收数据时,将触发回调,然后可以通过调用setValue从mediatorLiveData发出回调

public class ExerciseViewModel extends AndroidViewModel {
    ExercisesRepository repository;
    MediatorLiveData<List<Exercise>> mediatorLiveData = new MediatorLiveData<>();

    public ExerciseViewModel(Application application) {
        super(application);
        this.repository = new ExercisesRepository(application);
    }

    public void setFilters(String muscleGroups, String type) {
        LiveData<List<Exercise>> repositoryLiveData = this.repository.filterSelect(muscleGroups, type);
        mediatorLiveData.addSource(repositoryLiveData, exercisList -> {
            mediatorLiveData.removeSource(repositoryLiveData);
            mediatorLiveData.setValue(exercisList);
        });
    }

    public LiveData<List<Exercise>> select() {
        return mediatorLiveData;
    }
public类ExerciseViewModel扩展了AndroidViewModel{
演习储备库;
MediatorLiveData MediatorLiveData=新的MediatorLiveData();
公共练习视图模型(应用程序){
超级(应用);
this.repository=newexerciserespository(应用程序);
}
公共void集合过滤器(字符串musclegroup,字符串类型){
LiveData repositoryLiveData=this.repository.filterSelect(MuscleGroup,类型);
mediatorLiveData.addSource(repositoryLiveData,exercisList->{
removeSource(repositoryLiveData);
mediatorLiveData.setValue(exerciselist);
});
}
公共LiveData选择(){
返回数据;
}

我通过使用MediaLiveData和转换解决了这个问题

现在我的ViewModel构造函数如下所示:

public ExerciseViewModel(Application application) {
    super(application);
    this.repository = new ExercisesRepository(application);
    this.filterMutableLiveData = new MutableLiveData<>();

    ExercisesFilter filter = new ExercisesFilter();
    filter.muscleGroup = "";
    filter.type = "";
    this.filterMutableLiveData.setValue(filter);

    LiveData<List<Exercise>> source = Transformations.switchMap(
        this.filterMutableLiveData, value -> repository.filterSelect(value.muscleGroup, value.type)
    );

    this.data.addSource(source, val -> this.data.setValue(val));
  }
使用这种方法,每次更新过滤器时,都会触发传递给Transformations.switchMap的函数以获取新数据。最后,新的LiveData对象被添加到MediatorLiveData对象,因此所有源都可以使用一个观察者


来源:

谢谢你的回答。不幸的是,这就是问题所在。我已经测试了你的建议,但仍然存在相同的问题。之前我返回了一个新的LiveData对象,它获取了正确的数据,但随后我需要创建一个新的observable,这不是正确的方法。loadAll函数返回空对象?loadAll retuns LiveDat一个对象,但这是一个新的LiveData对象。为了使用相同的可观察对象,我需要将其数据放在现有的可变LiveData中。因此,我使用LiveData.getValue()这就是返回null的内容。除非有其他我不知道的方法。对于使用相同的引用,您可以使用可编辑的答案。谢谢Chris。这实际上会起作用,所以我会将您的答案标记为正确。我实际上选择了使用介体和转换。我将在另一个答案中解释。
  public LiveData<List<Exercise>> filterSelect(String muscleGroups, String type) {
    return this.dao.filterSelect("%" + muscleGroups + "%", "%" + type + "%");
  }
 @Override
  public void onClick(View v) {
    this.exerciseViewModel.setFilters("Biceps", "weight");
    this.exerciseViewModel.select().observe(this, exercises -> {
      if (exercises != null) {
        this.recyclerViewerAdapter.updateDataset(exercises);
      }
    });
  }
public LiveData<List<Exercise>> filterSelect(String muscleGroups, String type) {

if(muscleGroups == "" && type == "") {
 return this.dao.loadAll()

}else {

return this.dao.filterSelect("%" + muscleGroups + "%", "%" + type + "%");

}
public class ExerciseViewModel extends AndroidViewModel {
    ExercisesRepository repository;
    MediatorLiveData<List<Exercise>> mediatorLiveData = new MediatorLiveData<>();

    public ExerciseViewModel(Application application) {
        super(application);
        this.repository = new ExercisesRepository(application);
    }

    public void setFilters(String muscleGroups, String type) {
        LiveData<List<Exercise>> repositoryLiveData = this.repository.filterSelect(muscleGroups, type);
        mediatorLiveData.addSource(repositoryLiveData, exercisList -> {
            mediatorLiveData.removeSource(repositoryLiveData);
            mediatorLiveData.setValue(exercisList);
        });
    }

    public LiveData<List<Exercise>> select() {
        return mediatorLiveData;
    }
public ExerciseViewModel(Application application) {
    super(application);
    this.repository = new ExercisesRepository(application);
    this.filterMutableLiveData = new MutableLiveData<>();

    ExercisesFilter filter = new ExercisesFilter();
    filter.muscleGroup = "";
    filter.type = "";
    this.filterMutableLiveData.setValue(filter);

    LiveData<List<Exercise>> source = Transformations.switchMap(
        this.filterMutableLiveData, value -> repository.filterSelect(value.muscleGroup, value.type)
    );

    this.data.addSource(source, val -> this.data.setValue(val));
  }
 public void setFilterMutableLiveData(String muscleGroups, String type) {
    ExercisesFilter filter1 = new ExercisesFilter();
    filter1.muscleGroup = muscleGroups;
    filter1.type = type;
    this.filterMutableLiveData.setValue(filter1);
  }