【问题标题】:Android Room - Get the id of new inserted row with auto-generate - MVVM VersionAndroid Room - 使用自动生成获取新插入行的 id - MVVM 版本
【发布时间】:2020-12-18 06:54:06
【问题描述】:

正如这里Android Room - Get the id of new inserted row with auto-generate 所讨论的,可以从新插入的对象中获取 ID。

但是如何以 MVVM 模式从 DAO 到我的 Activity 类获取这个 ID?

那里的一些answers 建议使用rxjava 和类似的东西:
return Single.fromCallable<Long> { recipesDao.insertManual(cookingRecipes) }
但是为了一个方法调用而实现两个完整的 Gradle 依赖是否有意义?

难道没有办法让我目前的结构能够做到这一点吗?

Activity - ViewModel - Repository (-AsyncTask) - Dao


唯一的问题是从插入语句中获取返回值,该语句是从AsyncTask 调用的:

private static class UpdateChallengeInfosAsyncTask extends AsyncTask<ChallengeInfos, Void, Void> {

        private ChallengeInfosDao mAsyncTaskDao;

        UpdateChallengeInfosAsyncTask(ChallengeInfosDao dao) {
            mAsyncTaskDao = dao;
        }

        @Override
        protected Void doInBackground(ChallengeInfos... challengeInfos) {
            mAsyncTaskDao.insert(challengeInfos[0]);
            return null;
        }
    }

也许可以像这里一样使用onPostExecute() + Interface 组合?
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?

【问题讨论】:

标签: android mvvm android-asynctask android-room sql-insert


【解决方案1】:

只需将 AsyncTask 设为 Activity 中的嵌套类即可。然后你可以从onPostExecute()调用属于你的Activity的方法来传递ID值。

免责声明:AsyncTask 很糟糕,您应该使用其他东西。

免责声明 2:如果您关注 MVVM,则 ViewModel 应该处理 ID 而不是 Activity。

【讨论】:

  • 那么问题是,在创建一个新对象时,它的 ID 为 0。只有在再次检索它(通过关闭和打开活动)之后,它才会收到它在数据库中的实际 ID。所以问题是,我创建了对象,然后想要更新它,但由于 Room 找不到 ID“0”而失败。这就是为什么我需要将该 ID 分配给我在 Activity 中创建的对象。
  • AsyncTasks 不好的任何具体原因或者我可以用什么代替?
  • 好吧,看到 Concurrency here 的相对较长的实现,我认为没有必要仅仅为一些数据库写入重写我的逻辑,因为它们不应该有内存泄漏的风险或类似的东西,这似乎是人们害怕使用AsynkTask的原因
【解决方案2】:

好吧,我最终做了什么,看起来效果不错的是:

基本上使用了这个答案的结构:
https://stackoverflow.com/a/12575319/1972372

并在我的ViewModel 中使用MutableLiveData 对象实现AsynTask 回调接口,以便活动在开始时调用一次并一直保持到更新一次:


public class ChallengeViewModel extends AndroidViewModel implements ChallengesRepository.UpdateChallengeInfosAsyncTask.AsyncResponse {
    
    private MutableLiveData<Integer> insertedChlgInfoID;

....
....

    public void insertChallengeInfos(ChallengeInfos challengeInfos) {
        mRepository.insertChallengeInfos(challengeInfos, this);
    }

    public LiveData<Integer> getInsertedChlgInfoID() {
        return insertedChlgInfoID;
    }

    @Override
    public void processFinish(Long result) {
        insertedChlgInfoID.setValue(Ints.checkedCast(result));
    }
}

我理解AsyncTask 在某些情况下可能被称为坏的原因,但我认为在我的情况下它确实工作得很好,并且没有任何潜在的内存泄漏或类似风险,因为它只是非常基本的写入操作。重写整个逻辑似乎对我的情况没有任何好处。

【讨论】:

    猜你喜欢
    • 2017-11-05
    • 2011-04-03
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 2011-11-18
    • 2019-06-07
    • 2013-10-06
    • 1970-01-01
    相关资源
    最近更新 更多