如何为另一个ViewModel中的对象属性派生ViewModel?

问题描述 投票:0回答:1

我想为另一个ViewModel中保存的另一个对象的属性获取ViewModel。

我有这种关系:在一间房子里有多个人。 (在房屋表中而不是在联接表中对人进行编码的1:n关系。)在这种情况下,我有一个问题:现有房屋将在HouseDetailsActivity中显示,其中包含HouseDetailsFragment和PeopleListFragment。 HouseDetailsActivity在onCreate中获取HouseViewModel,如下所示:

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中。 HouseDetailsActivity(HouseDetailsViewModel)内部的HouseEntity中的人员列表不是L​​iveData。 (我希望能够通过PeopleListViewModel在PeopleListFragment中的HouseEntity中查看人员列表。)

我看过MediatorLiveData的文档,在这里我认为它不适用,因为最终PeopleList只有1个来源。

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
    });
}
android viewmodel android-livedata android-viewmodel
1个回答
0
投票

我看到您对这两个视图模型的初始化不同。

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

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

只需更改:

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

对此:

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

您可以在一个视图中初始化两个视口。不要对此害羞。

© www.soinside.com 2019 - 2024. All rights reserved.