LiveData not updating when data changes

前端 未结 1 1014
半阙折子戏
半阙折子戏 2021-02-09 06:33

I\'m using LiveData to fetch data from a server and observe it. My onChanged() method just gets called the first time, and does not get called when data in the serv

相关标签:
1条回答
  • 2021-02-09 07:23

    The issue is that fetchUser creates a new LiveData<> every time you call it.

    This means that your first one will never receive an update.

    Please take a look at these...

    Repository

    public class UserRepository {    
        private ApiService apiService;
        private static UserRepository userRepository;
    
        private UserRepository() {
            apiService = RestClient.getClient().create(ApiService.class);
        }
    
        public synchronized static UserRepository getInstance() {
            if (userRepository == null) userRepository = new UserRepository();
            return userRepository;
        }
    
        // Your example code
        public LiveData<User> fetchUser() {
            // Your problem lies here. Every time you fetch user data, you create a new LiveData.
            // Instead, fetch user should update the data on a pre-existing LiveData.
            final MutableLiveData<User> data = new MutableLiveData<>();
            Call<User> call = apiService.getUser();
            call.enqueue(new Callback<User>() {
                @Override
                public void onResponse(@NonNull Call<User> call, @NonNull Response<User> response) {
                    if (response.body() != null) {
                        data.postValue(response.body());
                    }
                }
    
                @Override
                public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
                    data.postValue(null);
                    t.printStackTrace();
                }
            });
            return data;
        }
    
        // My alterations below:
        private MutableLiveData<User> userLiveData = new MutableLiveData<>();
    
        public LiveData<User> getUser() {
            return userLiveData;
        }
    
        public LiveData<User> fetchUser2() {
            Call<User> call = apiService.getUser();
            call.enqueue(new Callback<User>() {
                @Override
                public void onResponse(@NonNull Call<User> call, @NonNull Response<User> response) {
                    if (response.body() != null) {
                        userLiveData.postValue(response.body());
                    }
                    // TODO: Consider a fallback response to the LiveData here, in the case that bad data is returned. Perhaps null?
                }
    
                @Override
                public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
                    userLiveData.postValue(null);
                    t.printStackTrace();
                }
            });
            return userLiveData;
        }
    }
    

    ViewModel

    I would also change this slightly. Instead of observing fetch, I would observe the LiveData directly.

    user = UserRepository.getInstance().getUser();
    

    Later, you can request updated data from the server at any point.

    UserRepository.getInstance().fetchUser2();
    

    You could also call fetchUser2() on the first construction of UserRepository. Then only updates would call fetchUser2() directly.

    private UserRepository() {
        apiService = RestClient.getClient().create(ApiService.class);
        fetchUser2();
    }
    

    Fragment

    Also, in your Fragment, do not observe on this. Instead use getViewLifecycleOwner()

    userViewModel.getUser().observe(getViewLifecycleOwner(), new Observer<User>() {
        @Override
        public void onChanged(User user) {
            //Set UI
        }
    });
    
    0 讨论(0)
提交回复
热议问题