如何使用存储库和ViewModel更新会议室数据库中的字段

时间:2019-05-11 08:09:55

标签: java android sqlite android-room

我在此guide from code labs之后创建了一个会议室数据库,它利用存储库来进行以下操作:

  

存储库管理查询线程,并允许您使用多个后端。在最常见的示例中,存储库实现了用于确定是从网络中获取数据还是使用本地数据库中缓存的结果的逻辑。

我遵循了指南,现在可以创建实体的&检索数据了。我什至走得更远,并在指南的范围之外创建了另一个整体。

但是,我找不到使用此MVVM(?)样式的许多资源,因此很难真正了解存储库。现在,我想更新一个字段。只是一个,就好像我能够管理其余的一样。

我想更新一个名为dartshit的字段,并为此创建了dao方法:

@Query(“ UPDATE AtcUserStats SET dartsHit =:amount WHERE userName =:userName”)     void UpdateHitAmount(int amount,String userName);

我有一个用于所有实体的存储库:

public class UsersRepository {

private UsersDao mUsersDao;
private AtcDao mAtcDao;
private LiveData<List<Users>> mAllUsers;
private LiveData<List<AtcUserStats>> mAllAtc;
private AtcUserStats mAtcUser;

UsersRepository(Application application) {
    AppDatabase db = AppDatabase.getDatabase(application);
    mUsersDao = db.usersDao();
    mAtcDao = db.atcDao();
    mAllUsers = mUsersDao.fetchAllUsers();
    mAllAtc = mAtcDao.getAllAtcStats();
}

LiveData<List<Users>> getAllUsers() {
    return mAllUsers;
}

LiveData<List<AtcUserStats>> getAllAtcStats() {
    return mAllAtc;
}

LiveData<AtcUserStats> getAtcUser(String username) {

    return mAtcDao.findByName(username);
}

public void insert (Users user) {
    new insertAsyncTask(mUsersDao).execute(user);
}

public void insertAtc (AtcUserStats atc) {
    new insertAsyncAtcTask(mAtcDao).execute(atc);
}

private static class insertAsyncTask extends AsyncTask<Users, Void, Void> {

    private UsersDao mAsyncTaskDao;

    insertAsyncTask(UsersDao dao) {
        mAsyncTaskDao = dao;
    }

    @Override
    protected Void doInBackground(final Users... params) {
        mAsyncTaskDao.insertNewUser(params[0]);
        return null;
    }
}

private static class insertAsyncAtcTask extends AsyncTask<AtcUserStats, Void, Void> {

    private AtcDao mAsyncTaskDao;

    insertAsyncAtcTask(AtcDao dao) {
        mAsyncTaskDao = dao;
    }

    @Override
    protected Void doInBackground(final AtcUserStats... params) {
        mAsyncTaskDao.insertNewAtcUser(params[0]);
        return null;
    }
}
}

我的问题是如何为要在此存储库中运行的更新查询创建AsyncTask?

到目前为止,这里是我大致复制插入存储库方法的内容:

private class updateHitAsyncTask {

    private AtcDao mAsyncTaskDao;

    public updateHitAsyncTask(AtcDao mAtcDao) {

        mAsyncTaskDao = mAtcDao;
    }

    protected Void doInBackground(int amount, String name) {
        mAsyncTaskDao.UpdateHitAmount(amount, name);
        return null;
    }
}

这是不正确的,因为我得到了一个 llegalStateException:无法访问主线程上的数据库,因为它可能长时间锁定UI。错误。但是我以为这个AsyncTask应该照顾这个?

这是我的视图模型中的更新方法,该方法报告0个错误:

  void updateHitAmount (int amount, String name) {
    mRepository.updateAtcHits(amount, name);
}

这是UI代码,我实际上试图将所有这些联系在一起,我怀疑必须有一个更好的方法,使用onChanged来简单地更新字段,但是我仍在努力寻找有关存储库的google上的任何建议方法:

   private void callOnChanged() {

    mAtcViewModel = ViewModelProviders.of(this).get(AtcViewModel.class);

    mAtcViewModel.getAllUsers().observe(this, new Observer<List<AtcUserStats>>() {
        @Override
        public void onChanged(@Nullable final List<AtcUserStats> atc) {
            // Update the cached copy of the users in the adapter.


            for (int i = 0; i < atc.size(); i++) {
                if (atc.get(i).getUserName().equals(mUser)) {
                    mAtcViewModel.updateHitAmount(55, mUser);
                    //atc.get(i).setDartsHit(55);
                    Log.d("id", String.valueOf(userSelected.getId()));
                }
            }
        }
    });

如何在后台线程上使用这种方法更新字段?

1 个答案:

答案 0 :(得分:0)

通过此答案here找出了答案。主要原因是我对AsyncTask缺乏了解。本质上,我需要创建一个对象并以这种方式传递数据,然后在后台执行:

 private static class MyTaskParams {
    int amount;
    String name;

    MyTaskParams(int amount, String name) {
        this.amount = amount;
        this.name = name;
    }
}

public void updateAtcHits (int amount, String name) {

    MyTaskParams params = new MyTaskParams(amount,name);
    new updateHitAsyncTask(mAtcDao).execute(params);
}

private class updateHitAsyncTask extends AsyncTask<MyTaskParams,Void,Void>{

    private AtcDao mAsyncTaskDao;

    public updateHitAsyncTask(AtcDao mAtcDao) {

        mAsyncTaskDao = mAtcDao;
    }

    @Override
    protected Void doInBackground(MyTaskParams... myTaskParams) {
        int amount =myTaskParams[0].amount;
        String name = myTaskParams[0].name;
        mAsyncTaskDao.UpdateHitAmount(amount, name);
        return null;
    }
}