问题
I'm studying the MVVM to see if it can help me for my upcoming projects. What I understand so far, is that I need to use a ViewModel for holding my UI datas. I also need to use a Repository class to perform all my Requests to WebServices, and I'm using the Volley Library.
So here's what I did :
The ViewModel
public class MyViewModel extends ViewModel {
private MyRepository repository;
private MutableLiveData<MyPojo> pojo;
public MyViewModel(MyRepository repository) {
this.repository = repository;
this.pojo = new MutableLiveData<>();
}
public LiveData<MyPojo> updatePojo(){
pojo.postValue(repository.getPojo());
return pojo;
}
}
The Repository class
public class MyRepository {
private Application application;
private LiveData<MyPojo> pojo;
public MyRepository(Application application) {
this.application = application;
}
public MyPojo getPojo(){
if(pojo == null){
ApiRequest apiRequest = new ApiRequest(ApiSingleton.getInstance(application).getRequestQueue(), application);
apiRequest.apiGetRequest(ApiRequest.MY_ENDPOINT, null, new ApiRequest.apiCallback() {
@Override
public void onSuccess(Context context, JSONObject jsonObject) {
pojo = ApiResponseParser.parse(jsonObject, MyPojo.class);
}
@Override
public void onError(Context context, String message) {
}
});
}
return pojo;
}
}
It's specified here that a ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context. As you can see, I must use a context in order to perform a Volley request in my Repository class, and my ViewModel has a reference on this class.
Am I missing something in my design? Is Volley not compatible here?
回答1:
Instead of passing the Application
to your MyRepository's constructor
and creating ApiRequest
, you can pass the ApiRequest
to MyRepository's constructor
.
public MyRepository(ApiRequest apiRequest) {
this.apiRequest = apiRequest;
}
Now the MyRepository
has no reference to Context
.
And, regarding ViewModel
having direct reference to MyRepository
, you can do dependency inversion:
Create an interface
, for instance, MyDataStore
with the method getPojo()
. MyRepository
will implement this interface
. While creating MyViewModel
, you will pass the MyRepository
to it, but MyViewModel
will only have reference to MyDataStore
.
interface MyDataStore {
... getPojo()
}
public class MyRepository implements MyDataStore {
...
}
public MyViewModel(MyDataStore dataStore) {
this.dataStore = dataStore;
this.pojo = new MutableLiveData<>();
}
回答2:
The LifeCycle library provides the AndroidViewModel component, which is just an Application's context aware ViewModel, pretty close to Bob's answer, and did the job here without memory leaks hazards.
来源:https://stackoverflow.com/questions/59331734/mvvm-architecture-in-android-using-volley