Hello, Vinicius!
Considering high cohesion and level of involvement the response is nay. In your code, you delegate tasks to ViewModel
which relate to the Repository
. How do you consider the use of a Repository
, let him do the work himself and only then pass the data to ViewModel
, leaving you in charge of UI management (Activity
/Fragment
) and your requests to this data. Let’s see in practice:
Messagesrepository.class
public class MessagesRepository {
private MutableLiveData<ArrayList<Message>> mMessages;
public MutableLiveData<ArrayList<Message>> getMessages(String uid) {
if(mMessages == null) mMessages = new MutableLiveData();
// Faça sua chamada a base de dados aqui e use
// o método postValue() do MutableLiveData em resultados
// de chamadas assíncronas
return mMessages;
}
}
Messagesviewmodel.class
public class MessagesViewModel extends ViewModel {
private MessagesRepository mRepository;
public MessagesViewModel(MessagesRepository repository) {
mRespository = repository;
}
public MutableLiveData<ArrayList<Message>> getMessages(String uid) {
return mRepository.getMessages(uid);
}
}
Realize that now the Repository
is solely responsible for obtaining the data, regardless of where they are, as the ViewModel
does not know where they come from. They may come from a local storage or an API, for example. This way, you can change your data source at any time without causing side effects on the other components. This is what is recommended by the documentation. However, access to the data can be done directly on ViewModel
Your ViewModel
should not make any kind of decision or do anything other than submit the data to the UI, such as treat ProgressBar
or Dialog
. For that, use a Resource
to be notified of the request status (loading, failure, empty, etc.).
EDIT 1:
1 - Create a Resource
to "traffic" data and call states to ViewModel
Resource.java
public class Resource<T> {
private State state;
private T data;
private String message;
public void setData(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
2 - Create a enum
to represent the states (these are basic states of any request)
Java state.
public enum State {
SUCCESSFUL,
FAILURE,
EMPTY
}
3 - Update the Repository
and the ViewModel
to work with Resource
Messagesrepository.class
public class MessagesRepository {
private MutableLiveData<Resource<ArrayList<Message>>> mMessages;
public MutableLiveData<Resource<ArrayList<Message>>> getMessages(String uid) {
if(mMessages == null) mMessages = new MutableLiveData();
// Seta o estado inicial e manda isso p/ ViewModel/UI
Resource<ArrayList<Message>> resource = new Resource<>();
resource.setState(State.LOADING);
mMessages.setValue(resource);
// Faça sua chamada a base de dados aqui e use
// o método postValue() do MutableLiveData em resultados
// de chamadas assíncronas. Não esqueça de setar os estados
// de sucesso e falha
return mMessages;
}
}
Messagesviewmodel.class
public class MessagesViewModel extends ViewModel {
private MessagesRepository mRepository;
public MessagesViewModel(MessagesRepository repository) {
mRespository = repository;
}
public MutableLiveData<Resource<ArrayList<Message>>> getMessages(String uid) {
return mRepository.getMessages(uid);
}
}
4 - Now in your UI
just manage the states showing loading/progress/alert
and other things
Messagesactivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messages);
mMessagesModel.getMessages(/* uid */)
.observe(this, resource -> {
if(resource.getState() == State.LOADING) {
// Carregando
}
else if (resource.getState() == State.SUCCESSFUL) {
// Carregado com êxito
ArrayList<Message> messages = resource.getData();
}
else if (resource.getState() == State.FAILURE) {
// Falha
}
else {
// Vazio
}
});
}
That’s the basics. Everything can improve, especially in development. Use this as a starting point. I hope it helps!
Very cool your answer, I have implemented the suggested pattern and it was much better and intelligible. Now, to get the status of the request, do you have an example of how I can use this Resource? That part for me is still a little abstract.
– Vinícius Rodrigues
I updated my answer. I implemented an example of using
Resource
– Ivan Silva