问题
I am trying to set data onto the ViewModel in a file in which I do not wish to hold any activity references.
Class A -> set data onto the LiveData in ViewModel Has an Application class reference but does not hold activity or fragment
Class B -> read data from the LiveData in ViewModel Has a reference to the activity.
Class B can be destroyed and recreated along with the Activity's config changes. Class A is persistent in memory and keeps setting data to the LiveData
Problem: ViewModelProviders.of(activity or fragment).get() ViewProviders need activity or fragment instance.
回答1:
ViewModels are strongly tied to Activity's and Fragment's lifecycle so you cannot use them with application context and need to use Activity's and Fragment's context.
If you want to share data between fragments you can use getActivity()
to get the same ViewModel which will hold your data and will survive as long as your Activity is in scope.
回答2:
You can use AndroidViewModel, it is attached with application lifecycle.
An example:
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);
}
/**
* Expose the LiveData Comments query so the UI can observe it.
*/
public LiveData<List<CommentEntity>> getComments() {
return mObservableComments;
}
public LiveData<ProductEntity> getObservableProduct() {
return mObservableProduct;
}
public void setProduct(ProductEntity product) {
this.product.set(product);
}
/**
* 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);
}
}
}
来源:https://stackoverflow.com/questions/55307761/create-viewmodel-with-application