Как получить ViewModel для атрибута объекта в другой ViewModel? - PullRequest
0 голосов
/ 29 октября 2019

Я хочу получить 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
    });
}

1 Ответ

0 голосов
/ 29 октября 2019

Я вижу, вы по-разному инициализировали эти две модели представления.

houseViewModel = ViewModelProviders.of (this, new HouseViewModel.Factory (getApplication (), id)). Get (HouseViewModel.class);

peopleListViewModel = ViewModelProviders.of (this) .get (PeopleListViewModel.class);

Просто измените:

houseViewModel = ViewModelProviders.of (это, новый HouseViewModel.Factory (getApplication (), id)). get (HouseViewModel.class);

к этому:

houseViewModel = ViewModelProviders.of (this,ViewModelProviders.of (this) .get (HouseViewModel.class);

Вы можете инициализировать две viewmdoels в представлении. Не стесняйтесь.

...