当前位置: 首页 > 知识库问答 >
问题:

Android-room持久库-DAO调用是异步的,因此如何获得回调?

苗森
2023-03-14

据我所知,Room不允许您在主线程上发出数据库查询(这可能会导致主线程上的延迟)。想象一下,我正试图在UI主线程上更新一个textview,其中包含一些数据,我将如何获得回拨。让我给你举个例子。假设我想将业务模型数据存储到一个名为Events的对象中。因此,我们将有一个EventDao对象:

想象我们在下面有这个DAO对象:

@Dao
public interface EventDao {

   @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate" limit 1)
   LiveData<List<Event>> getEvent(LocalDateTime minDate);

   @Insert(onConflict = REPLACE)
   void addEvent(Event event);

   @Delete
   void deleteEvent(Event event);

   @Update(onConflict = REPLACE)
   void updateEvent(Event event);

}

现在在一些活动中,我有一个文本视图,我想更新它的值,所以我这样做:

 myTextView.setText(EventDao.getEvent(someDate));/*i think this is illegal as im trying to call room dao on mainthread, therefore how is this done correctly ? would i need to show a spinner while it updates ?*/

因为抓取发生在主线程之外,所以我不认为我可以这样称呼它,并期待顺利更新。这里最好的方法是什么?

更多信息:我想使用房间数据库作为检索模型信息的机制,而不是将其静态保存在内存中。因此,在我通过rest服务下载模型后,我可以通过db在本地访问该模型。

更新:既然我返回了一个livedata,那么我可以这样做:

eventDao = eventDatabase.eventDao();
eventDao.getEvent().observe(this, event -> {
     myTextView.setText(event.get(0));
});

这适用于非常小的东西。但是想象一下我的数据库有一百万个项目。然后当我做这个调用时,检索数据会有延迟。第一次调用它时,用户会看到有延迟。如何避免这种情况?所以要明确的是,有时我不想要实时数据,我只需要更新一次视图。我需要知道如何做到这一点?即使它不使用liveData。

共有3个答案

章兴发
2023-03-14

正如Bohsen建议使用livedata同步查询。但在某些特殊情况下,我们希望基于逻辑进行一些异步操作。在下面的示例情况下,我需要为父注释获取一些子注释。它在DB中已经可用,但需要根据其在回收器视图适配器中的parent_id获取。为此,我使用了AsyncTask的返回概念来获取结果。(在静态编程语言中返回)

重置类

fun getChildDiscussions(parentId: Int): List<DiscussionEntity>? {
        return GetChildDiscussionAsyncTask(discussionDao).execute(parentId).get()
    }

private class GetChildDiscussionAsyncTask constructor(private val discussionDao: DiscussionDao?): AsyncTask<Int, Void, List<DiscussionEntity>?>() {
        override fun doInBackground(vararg params: Int?): List<DiscussionEntity>? {
            return discussionDao?.getChildDiscussionList(params[0]!!)
        }
    }

刀类

@Query("SELECT * FROM discussion_table WHERE parent_id = :parentId")
fun getChildDiscussionList(parentId: Int): List<DiscussionEntity>?
韩弘方
2023-03-14

有一种方法可以关闭异步并允许同步访问。

构建数据库时,可以使用:allowMainThreadQueries()

并在内存中使用:Room.inMemoryDatabase aseBuilder()

虽然不推荐。因此,如果我想要超级快速的访问,我最终可以使用内存中的数据库和主线程访问。我想这取决于我的数据有多大,在这种情况下是非常小的。

但是如果您确实想使用回调......这里使用rxJava是我为我想存储在数据库中的国家列表制作的:

public Observable<CountryModel> queryCountryInfoFor(final String isoCode) {
    return Observable.fromCallable(new Callable<CountryModel>() {
        @Override
        public CountryModel call() throws Exception {
            return db.countriesDao().getCountry(isoCode);
        }
    }).subscribeOn(Schedulers.io())
       
 .observeOn(AndroidSchedulers.mainThread());

}

然后,您可以轻松地向该函数添加订阅者,以使用Rxjava获得回调。

经骁
2023-03-14

如果您希望同步执行查询,并且不接收数据集更新的通知,请不要将返回值包装在LiveData对象中。查看谷歌的示例代码。

在此处查看loadProductSync()

 类似资料:
  • 下面是Kotlin中的类: 但当我试图运行应用程序时,它立即崩溃。以下是崩溃日志: 类似乎不是自动生成的。我检查了从codelab下载的原始java应用程序,发现是自动生成的。

  • 我试图通过新的android room库更新我的数据库,但它不起作用。这就是我的方法 主要活动。JAVA CarViewModel。JAVA 卡ao.java 我做了调试,新数据出现并调用viewModel。updateItems(list)方法。提前谢谢!

  • 我正在使用android的房间持久性库,如果有人能帮助我使用外键,如何通过使用外键获取数据,我将不胜感激。

  • 在我的测试应用程序中,我使用Apache HttpClient向同一主机执行连续的HttpGet请求,但在每个下一个请求时,都会发现之前的HttpConnection被关闭并创建新的HttpConnection。 我使用同一个HttpClient实例,不关闭响应。我从每个实体获取InputStream,用扫描仪读取,然后关闭扫描仪。我测试了KeepAlivestStrategy,结果是真的。请求之

  • 我想使用预先填充的数据库的房间,但我不明白如何告诉房间在哪里找到我的数据库。 现在我将它放在中,当我为房间数据库创建实例时,我是这样创建的: 这样一来,我认为它每次都在创建一个新的数据库,或者说,它没有使用预填充的数据库。 我怎样才能找到我的数据库?

  • 问题内容: 作为开始使用Android的iOS开发人员,我遇到了Retrofit。我了解如何实现同步请求,但是在通过成功/失败回调实现异步请求时遇到了麻烦。具体来说,我不清楚Callback语法,在Retrofit 网站,介绍Retrofit 的Square 博客文章或我所见过的其他地方都没有具体的示例。有人可以在此发布一些示例代码吗?我在改造仓库中提出了一个问题,要求他们使用此信息更新自述文件。