android - 如何为另一个 ViewModel 中的对象属性派生 ViewModel?
问题描述
我想为另一个 ViewModel 中保存的另一个对象的属性获取一个 ViewModel。
我有这样的关系:在一个房子里有很多人。(人在 Houses 表中编码的 1:n 关系,而不是使用连接表。)在这种情况下我有一个问题:现有的 House 将显示在 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 中的人员列表不是 LiveData。(我希望能够通过 PeopleListViewModel 在 PeopleListFragment 中查看 HouseEntity 的人员列表。)
我已经看过 MediatorLiveData 的文档,我认为这里不适用,因为最终只有一个 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
});
}
解决方案
我看到您以不同的方式初始化了这两个视图模型。
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);
你可以在一个视图中初始化两个viewmdoel。不要害羞。
推荐阅读
- google-cloud-platform - 哪些是用于将对象复制到 Cloud Storage 存储分区的凭据
- git - Git 从终端使用正确的用户提交,但不是从 VS Code 提交
- php - È char 保存为 ? 在文件 php
- angular-calendar - 为什么 Angular 日历只显示纯文本和数字?
- python-3.7 - 是否有更快的方法来检查网站末尾的每个字符串
- laravel - laravel elasticsearch 只是从第一个模型中搜索
- javascript - 在正则表达式中使用动态数据
- postgresql - 包含 pgAdmin 4 v2.1 的 PostgreSQL 版本是什么?
- html - “在资源包中定义此标签”错误 sonarqube
- javascript - puppeteer 在运行所有笑话测试之前关闭浏览器