Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
124 views
in Technique[技术] by (71.8m points)

observer pattern - Android ViewModel: Should I "borrow" the observe() method from LiveData like in the official example?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...