我正在查看Android架构组件样本中的BasicSample应用程序。在ProductViewModel.java文件中,读取了一些注释:
不是 在这种情况下实际上是必要的,因为产品ID可以在公共方法中传递。
根据我对评论的理解,我想知道是否可以在不使用工厂的情况下将productId传递给ProductViewModel,以及如何做到这一点。
我已经实现了Transformation,我知道我可以使用switchMap传递productId。但我正在寻找一种方法来用一个id来初始化模型。
public class ProductViewModel extends AndroidViewModel {
private final LiveData<ProductEntity> mObservableProduct;
public ObservableField<ProductEntity> product = new ObservableField<>();
private final int mProductId;
private final LiveData<List<CommentEntity>> mObservableComments;
public ProductViewModel(@NonNull Application application, DataRepository repository,
final int productId) {
super(application);
mProductId = productId;
mObservableComments = repository.loadComments(mProductId);
mObservableProduct = repository.loadProduct(mProductId);
}
...
/**
* A creator is used to inject the product ID into the ViewModel
* <p>
* This creator is to showcase how to inject dependencies into ViewModels. It's not
* actually necessary in this case, as the product ID can be passed in a public method.
*/
public static class Factory extends ViewModelProvider.NewInstanceFactory {
@NonNull
private final Application mApplication;
private final int mProductId;
private final DataRepository mRepository;
public Factory(@NonNull Application application, int productId) {
mApplication = application;
mProductId = productId;
mRepository = ((BasicApp) application).getRepository();
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
//noinspection unchecked
return (T) new ProductViewModel(mApplication, mRepository, mProductId);
}
}
}
答案 0 :(得分:2)
参考样本时,评论说:
产品ID可以通过公共方法传递
这指的是您可以创建公共setter方法。
由于productId
用于从您的数据库获取LiveData,因此您应该使用switchMap
,如您所述。这是因为switchMap
允许您查找和更新LiveData
指向的内容,而无需重新设置观察者。如果您没有使用switchMap
,则需要告诉您的活动观察新查找的LiveData
,并可能停止观察旧的LiveData
对象。 More description of this is included in the docs
还有一点需要注意 - 工厂在这里也很有用,因为你通过构造函数传入或者注入 DataRepository
依赖项。这是将存储库放入类中的一种更好的方法,因为在测试时可以很容易地模拟存储库。
考虑到这一点,如果你想这样做是工厂,你的代码可能看起来像:
public class ProductViewModel extends AndroidViewModel {
private final LiveData<ProductEntity> mProduct;
private final LiveData<List<CommentEntity>> mComments;
private final MutableLiveData<Integer> mProductId = new MutableLiveData<>();
public ProductViewModel(@NonNull Application application) {
super(application);
// Have some way to get your repository, this is not great for testing...
Repository repository = ((BasicApp) application).getRepository();
mProduct = Transformations.switchMap(mProductId, id -> {
return repository.loadProduct(id);
}
mComments = Transformations.switchMap(mComments, id -> {
return repository.loadComments(id);
}
}
public void setProductId(int productId) {
mProductId.setValue(productId); // This will trigger both of those switchMap statements
}
}
答案 1 :(得分:0)
productId 来自哪里?
如果它是从存储库(数据库或Web服务)加载的,那么您不必在ViewModel上公开它。
如果它是一个“动态”值,存储在SharedPreferences中或从视图中设置,您可以公开一个Setter,如下所示
public void setProductId(int productId) {
if(mProductId == -1) { // or check mObservableComments
mProductId = productId;
mObservableComments = repository.loadComments(mProductId);
mObservableProduct = repository.loadProduct(mProductId);
}
}