dcanh121
dcanh121

Reputation: 4695

Create ViewModel with Application

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.

Upvotes: 6

Views: 12254

Answers (2)

Amrat Singh
Amrat Singh

Reputation: 331

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);

        }

    }

}

Upvotes: 4

Vygintas B
Vygintas B

Reputation: 1694

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.

Upvotes: 2

Related Questions