如何从后台服务和更新UI更新ViewModel的LiveData

时间:2017-05-26 15:15:19

标签: android viewmodel background-service android-room android-architecture-components

最近我正在探索谷歌最近推出的Android架构。从Documentation我发现了这个:

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 async operation to fetch users
    }
}

活动可以按如下方式访问此列表:

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

我的问题是,我将这样做:

    {li>

    loadUsers()函数中我异步获取数据,我将首先检查数据库(Room)中的数据

  1. 如果我没有获取数据,我将进行API调用以从Web服务器获取数据。

  2. 我会将获取的数据插入数据库(Room)并根据数据更新UI。

  3. 建议的方法是什么?

    如果我开始ServiceloadUsers()方法调用API,如何从MutableLiveData<List<User>> users更新Service变量?

6 个答案:

答案 0 :(得分:59)

我假设您正在使用android architecture components。实际上,无论您在何处调用service, asynctask or handler来更新数据都无关紧要。您可以使用postValue(..)方法从服务或asynctask插入数据。你的课程看起来像这样:

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
    users.postValue(listOfData)
}

由于usersLiveDataRoom数据库负责在任何位置插入用户数据。

Note:在类似MVVM的体系结构中,存储库主要负责检查和提取本地数据和远程数据。

答案 1 :(得分:41)

请使用后台主题中的实时数据&lt; postValue(..)方法。

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
   users.postValue(listOfData)
}

答案 2 :(得分:15)

  

...在loadUsers()函数中我异步获取数据...   如果我启动一个服务从loadUsers()方法调用API,如何   我可以更新MutableLiveData&gt;用户变量   服务?

如果应用在后台线程上提取用户数据,则postValue(而非setValue)将非常有用。

在loadData方法中,有一个对MutableLiveData“users”对象的引用。 loadData方法还从某个地方(例如,存储库)获取一些新的用户数据。

现在,如果执行在后台线程上,MutableLiveData.postValue()会更新MutableLiveData对象的外部观察者。

也许是这样的:

private MutableLiveData<List<User>> users;

.
.
.

private void loadUsers() {
    // do async operation to fetch users
    ExecutorService service =  Executors.newSingleThreadExecutor();
    service.submit(new Runnable() {
        @Override
        public void run() {
            // on background thread, obtain a fresh list of users
            List<String> freshUserList = aRepositorySomewhere.getUsers();

            // now that you have the fresh user data in freshUserList, 
            // make it available to outside observers of the "users" 
            // MutableLiveData object
            users.postValue(freshUserList);        
        }
    });

}

答案 3 :(得分:4)

查看LiveDataViewModel等新架构模块附带的Android architecture guide。他们深入讨论了这个问题。

在他们的例子中,他们没有把它放在服务中。看看他们是如何使用&#34;存储库&#34;来解决它的。模块和改造。底部的附录包括更完整的示例,包括通信网络状态,报告错误等。

答案 4 :(得分:2)

https://developer.android.com/topic/libraries/architecture/guide.html

对你的问题有很好的答案。一直滚动到底部,看看如何在数据库中保存响应并使用LiveData更新UI。

enter image description here

答案 5 :(得分:1)

如果要在存储库中调用api,则

存储库中:

public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) {
    final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>();
    apiService.checkLogin(loginRequestModel)
            .enqueue(new Callback<LoginResponseModel>() {
                @Override
                public void onResponse(@NonNull Call<LoginResponseModel> call, @Nullable Response<LoginResponseModel> response) {
                    if (response != null && response.isSuccessful()) {
                        data.postValue(response.body());
                        Log.i("Response ", response.body().getMessage());
                    }
                }

                @Override
                public void onFailure(@NonNull Call<LoginResponseModel> call, Throwable t) {
                    data.postValue(null);
                }
            });
    return data;
}

ViewModel

public LiveData<LoginResponseModel> getUser() {
    loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
    return loginResponseModelMutableLiveData;
}

活动/片段

loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
        if (loginResponseModel != null) {
            Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
        }
    });

注意:在此处使用JAVA_1.8 lambda,您可以不使用它