java - 数据更改时 LiveData 不更新

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

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

用户 fragment :

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

用户 View 模型:
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;
    }
}

最佳答案

问题是 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;
    }
}

View 模型

我也会稍微改变一下。我不会直接观察 fetch,而是直接观察 LiveData。
user = UserRepository.getInstance().getUser();

稍后,您可以随时从服务器请求更新数据。
UserRepository.getInstance().fetchUser2();

您也可以调用fetchUser2()UserRepository 的第一次 build 中.然后只有更新会调用 fetchUser2()直接地。
private UserRepository() {
    apiService = RestClient.getClient().create(ApiService.class);
    fetchUser2();
}

分段

此外,在您的 fragment 中,不要在 this 上观察.而是使用 getViewLifecycleOwner()
userViewModel.getUser().observe(getViewLifecycleOwner(), new Observer<User>() {
    @Override
    public void onChanged(User user) {
        //Set UI
    }
});

关于java - 数据更改时 LiveData 不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53406859/

相关文章:

java - 无法单击单选按钮,其中单选按钮更改 Web ui 页面上的顺序 Selenium Web Driver Java

java - 数据库中的事务在 android 中不起作用

Java 字节操作 - 将 3 字节转换为整数数据

java - 如何使用 Bloblstore API 更改上传到 GCS 的文件的名称

java - JPA 无法以多对一关系持久保存实体

java - 在 onMapReady 回调中使用 if 会产生问题吗?

具有固定边界框的 Android 相机预览

Android - 如果 View 模型包含 Activity 监听器引用,是否会发生内存泄漏?

android - Dao 方法返回 List<String> 而我需要一个 Map<String,Integer>

android - android中第二次观察viewmodel返回null