Я хочу получить ViewModel для атрибута другого объекта, хранящегося в другой ViewModel.
У меня есть такая связь: в доме много людей. (Соотношение 1: n, где люди кодируются в таблице Houses, а не в таблице соединений.) У меня есть проблема в этом сценарии: существующий дом должен отображаться в HouseDetailsActivity, который содержит HouseDetailsFragment и PeopleListFragment. HouseDetailsActivity возвращает HouseViewModel в onCreate, например:
houseViewModel = ViewModelProviders.of(this, new HouseViewModel.Factory(getApplication(), id)).get(HouseViewModel.class);
HouseViewModel может возвращать LiveData, поскольку он получает HouseEntity из базы данных. PeopleListFragment должен откуда-то получить LiveData для списка людей для этого дома, но не должен знать какие-либо модели представления, кроме PeopleListViewModel. Итак, также в HouseDetailsActivity onCreate я получаю PeopleListViewModel, например:
peopleListViewModel = ViewModelProviders.of(this).get(PeopleListViewModel.class);
, который, как я ожидаю, может быть разделен с PeopleListFragment, получая его так:
peopleViewModel = ViewModelProviders.of(getActivity()).get(PeopleListViewModel.class);
Проблема в том, как получить список людей в LiveData в ViewModel. Список людей в HouseEntity внутри HouseDetailsActivity (HouseDetailsViewModel) не является LiveData. (Я хочу видеть список людей из HouseEntity в PeopleListFragment через PeopleListViewModel.)
Я видел документацию для MediatorLiveData, которая, я думаю, здесь не применима, потому что в конечном итогеявляется только 1 источником PeopleList.
public class HouseDetailsActivity
{
protected void onCreate(Bundle savedInstanceState)
{
houseViewModel = ViewModelProviders.of(this, new HouseViewModel.Factory(getApplication(), id)).get(HouseViewModel.class);
peopleListViewModel = ViewModelProviders.of(this).get(PeopleListViewModel.class);
/* This can't be done, because the HouseEntity may not yet be loaded to the ViewModel. ie. NullPointerException here
List<Person> people = m_houseViewModel.getHouse().getPeopleList();
peopleListViewModel.setPeople(people);
*/
}
}
@Entity(tableName="houses")
public class HouseEntity implements MutableHouse
{
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name="hid")
public int id = 0;
@ColumnInfo(name="address")
private String address = null;
/** This is the encoded people, for multiple in a single database field. */
@ColumnInfo(name="residents")
private String residents = null;
public List<Person> getPeopleList ()
{ return HouseEncoding.decodePeople(getResidents()); }
...
}
public class HouseViewModel
{
private final int houseId;
private MutableLiveData<HouseEntity> house; // The list of people is inside house here, but not as LiveData
public LiveData<HouseEntity> getObservableHouse ()
{ return house; }
HouseViewModel (@NonNull Application application, int houseId)
{
super(application);
this.houseId = houseId;
this.house = getRepository().getHouseObservable(houseId);
}
/**
* A creator is used to inject the house ID into the ViewModel
*/
public static class Factory extends ViewModelProvider.NewInstanceFactory
{
@NonNull
private Application application;
private int houseId;
public Factory (@NonNull Application application, int houseId)
{
this.application = application;
this.houseId = houseId;
}
@Override
@NonNull
public <T extends ViewModel> T create (@NonNull Class<T> modelClass)
{
//noinspection unchecked
return (T) new HouseViewModel(application, houseId);
}
}
}
public class PeopleListViewModel
{
private MutableLiveData<List<Person>> people;
void setPeople (List<Person> people)
{ this.people.setValue(people); }
...
}
Внутри PeopleListFragment:
private void observerSetup ()
{
peopleViewModel.getPeople().observe(this, people -> {
adapter.setPeople(people); // for RecyclerView
});
}