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

Cod*_*meo 80 android background-service viewmodel android-room android-architecture-components

最近我正在探索谷歌最近推出的Android架构.从文档中我发现了这个:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,在loadUsers()我正在异步获取数据的函数中,我将首先检查数据库(Room)中的数据,如果我没有得到数据,我将进行API调用以从Web服务器获取数据.然后我将获取的数据插入数据库(Room)并根据数据更新UI.建议的方法是什么?

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

and*_*ter 87

我假设您正在使用Android架构组件.实际上,无论您在何处调用service, asynctask or handler更新数据都无关紧要.您可以使用postValue(..)方法从服务或asynctask插入数据.你的课将如下所示:

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

由于usersLiveData,Room数据库负责无论它插入为用户提供数据.

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

  • 我得到"java.lang.IllegalStateException:无法在主线程上访问数据库,因为它"调用我的db方法,如上所述,你能说出什么可能是错的吗? (3认同)
  • 我的错误是使用 `value` 而不是 `postValue`。感谢您的回答。 (2认同)
  • @pcj,您需要在线程中执行房间操作或在主线程上启用操作 - 谷歌以获取更多答案。 (2认同)

min*_*zur 44

请从后台线程使用实时数据的postValue(..)方法.

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

  • 要提醒的是,postValue()在LiveData中受到保护,但在MutableLiveData中是公共的 (14认同)

alb*_*aun 15

...在loadUsers()函数中我异步获取数据...如果我启动一个Service来从loadUsers()方法调用API,我如何从该服务更新MutableLiveData> users变量?

如果应用程序在后台线程上获取用户数据,则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);        
        }
    });

}
Run Code Online (Sandbox Code Playgroud)