数据更改时LiveData不更新

时间:2018-11-21 07:05:45

标签: java android android-architecture-components android-livedata android-viewmodel

我正在使用LiveData从服务器获取数据并进行观察。我的onChanged()方法只是第一次被调用,而服务器中的数据被更新时不会被调用。

用户片段:

UserViewModel userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.getUser().observe(this, new Observer<User>() {
    @Override
    public void onChanged(User user) {
        //Set UI
    }
});

UserViewModel:

public class UserViewModel extends AndroidViewModel {
    private LiveData<User> user;

    public UserViewModel(Application application) {
        super(application);
        user = UserRepository.getInstance().fetchUser();
    }

    public LiveData<User> getUser() {
        return user;
    }    
}

用户存储库:

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;
    }

    public LiveData<User> fetchUser() {
        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;
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于,每次调用fetchUser都会创建一个新的LiveData<>

这意味着您的第一个将永远不会收到更新。

请看看这些...

存储库

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

我也会对此稍作更改。与其观察获取,不如直接观察LiveData。

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

稍后,您可以随时从服务器请求更新的数据。

UserRepository.getInstance().fetchUser2();

您还可以在fetchUser2()的第一个结构上调用UserRepository。然后只有更新会直接调用fetchUser2()

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

片段

此外,在您的片段中,不要在this上进行观察。而是使用getViewLifecycleOwner()

userViewModel.getUser().observe(getViewLifecycleOwner(), new Observer<User>() {
    @Override
    public void onChanged(User user) {
        //Set UI
    }
});