代码之家  ›  专栏  ›  技术社区  ›  live-love

是否可以在没有工厂的公共方法中向AndroidViewModel传递id参数?

  •  2
  • live-love  · 技术社区  · 6 年前

    我正在查看Android架构组件示例中的BasicSample应用程序。在ProductViewModel中。java文件,一些注释如下:

    不是的 在这种情况下实际上是必要的,因为产品ID可以在公共方法中传递。

    根据我对评论的理解,我想知道是否有可能在不使用工厂的情况下将productId传递给ProductViewModel,以及如何做到这一点。

    我已经实现了转换,我知道我可以使用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);
            }
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   sanomik Lyla    6 年前

    关于样本,当评论说:

    可以在公共方法中传递产品ID

    这是指您可以创建一个公共setter方法。

    productId 用于从数据库中获取LiveData,您应该使用 switchMap ,如您所述。这是因为 开关映射 允许您查找和更新 LiveData 指向,无需重新设置观察者。如果你没有使用 开关映射 ,您需要告知您的活动以观察新查找的 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
        }
    
    }
    
        2
  •  0
  •   Gaëtan S    6 年前

    在哪里 产品ID 来自

    • 如果它是从存储库(数据库或web服务)加载的,我想您不必在ViewModel上公开它。

    • 如果它是一个“动态”值,存储在SharedReferences中或从视图中设置,则可以如下所示公开Setter

    .

     public void setProductId(int productId) {
           if(mProductId == -1) { // or check mObservableComments 
                  mProductId = productId;
                  mObservableComments = repository.loadComments(mProductId);
                  mObservableProduct = repository.loadProduct(mProductId);
           }
    }