问题
When working with ViewModels the View observes the ViewModel. It has to register as an observer. In the official tutorial of Google this registration is delegated to the observe()
method of a LiveData
object.
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
The method getUsers()
returns the LiveData
object itself. It's observe()
method is used to register the observer. The View does not observe the the ViewModel
but a part of it's implementation.
Now is this best practice, when working with ViewModels
not to observe themselves but parts of their implementation in form of LiveData
objects? Or is this an introduction of low quality?
回答1:
Based on the answer of Chris I give my own answer. I think the tutorial is not best practice for the simple reason, that an object should not expose it's internal implementation. Base on the argumentation of Chris I was looking for an option to get encapsulation without losing the named features. The result is the method observerUsers()
which delegates to a LiveData
object internally.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivityViewModel model = ViewModelProviders.of(this).get(MainActivityViewModel.class);
model.observeUsers(this,
new Observer<List<User>>() {
@Override
public void onChanged(@Nullable List<User> users) {
updateUI();
}
}
);
}
void updateUI() {
}
static class MainActivityViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public void observeUsers(@NonNull LifecycleOwner owner,
@NonNull Observer<List<User>> observer) {
getUsers().observe(owner, observer);
}
private LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
static class User {
}
}
Still List<User>
exposes internal implementation. It could be improved to a class Users
.
I put everything into one file and use inner static class. This is not meant as best practice. It was just to be able to quickly edit everything within one file. Especially the model User
belongs into it's very own file, while I often put the ViewModel
into the View
class it belongs to like this.
My second point of critic matches the case that the ViewModel
itself observes an underlying model. In this case the observer method onChange()
is very general and requires a very general update method like updateUI()
. You may want to observe more specific events of the model to do specific updates.
回答2:
I'd say yes it's best practice for the ViewModel to expose its data through some form of Observable, whether that be LiveData or something like an RX Observable.
This breaks from other architectures such as MVP where the presenter would typically have a reference to the View which gets called when something changes. The guidelines are quite specific about what a ViewModel should reference.
A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.
By exposing your data as an Observable through the ViewModel this means views can come and go, and once subscribed will receive the latest data and any subsequent updates. Again the guidelines have some detail.
If the activity is re-created, it receives the same MyViewModel instance that was created by the first activity. When the owner activity is finished, the framework calls the ViewModel objects's onCleared() method so that it can clean up resources
https://developer.android.com/topic/libraries/architecture/viewmodel.html
来源:https://stackoverflow.com/questions/49511750/android-viewmodel-should-i-borrow-the-observe-method-from-livedata-like-in