Android ViewModel: Should I “borrow” the observe() method from LiveData like in the official example?

孤人 提交于 2019-12-13 10:29:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!