gpt4 book ai didi

java - 为什么 android room 在生成它的异步任务(对象)的末尾插入一个对象?

转载 作者:行者123 更新时间:2023-11-30 10:02:30 25 4
gpt4 key购买 nike

总结

Room 立即插入通过 UI 生成的实体,但将异步任务发送的实体延迟到生成异步任务的(远)端:收到的实体对象可用并显示在 UI 上,但没有来自数据库的任何 id,妨碍任何其他操作依赖id。插入操作仅在生成的异步任务正确停止时发生:为什么?以及如何解决这个问题?

更多上下文

生成异步任务

我们使用异步任务来监控套接字并将一些事件(作为 Room 实体)发送回应用程序存储库(如 android 体系结构组件所预期的那样)。这个 asynctask 基本上在后台连续运行(定期设置一些 sleep )并且只在应用程序结束前停止一段时间(如果做得好)。到目前为止,它并没有给我们造成任何问题,以至于偏离了短暂的异步任务的原始概念。我非常清楚我们可以改进设计,但这是另一个主题/问题/时间漏洞;-)。

房间插入操作

插入是通过一个专用的异步任务进行的,其中数据库中条目的返回 ID 会影响到刚刚插入的实体(请参见下面的代码)。这被记录下来,UI 中的实体“立即”被持久化,他们取回了他们的 ID,一切都很好。 asynctask 生成的实体,它们会等待“父”任务停止,然后全部插入。

实体组成

实体首先在asynctask内部生成,通过progress消息发送。然后对象的构造被移到 asynctask 之外,并与 UI 事件构造处于同一级别,但行为相同。这些事件是一些 longs(时间戳)和几个字符串。

从这里开始生成异步任务:

    @Override
protected void onProgressUpdate(OnProgressObject... values) {
OnProgressObject onProgressObject = values[0];

if (onProgressObject instanceof OnProgressEvent) {
eventRecipient.sendAutoEvent(((OnProgressEvent) onProgressObject).autoEvent);
}
}

eventRecipient 是 EventsRepository:

    public void sendAutoEvent(AutoEvent autoEvent) {
Log.d(LOG_TAG, "got an autoevent to treat...");
EventModel newEvent = EventModel.fromCub(
autoEvent.cubTimeStamp,
autoEvent.description,
autoEvent.eventType
);
addEvent(newEvent);
}


public void addEvent(EventModel event) {

new insertEventAsyncTask(event).execute(event);

// other operations using flawlessly the "event"...
}

private class insertEventAsyncTask extends AsyncTask<EventModel, Void, Long> {
private EventModel eventModel;
public insertEventAsyncTask(EventModel eventModel) {
this.eventModel = eventModel;
}
@Override
protected Long doInBackground(EventModel... eventModels) {
// inserting the event "only"
return eventDao.insert(eventModels[0]);
}

@Override
protected void onPostExecute(Long eventId) {
super.onPostExecute(eventId);
// inserting all the medias associated to this event
// only one media is expected this way though.
eventModel.id = eventId;
Log.d(LOG_TAG, "event inserted in DB, got id : " + eventId);
}

}

最佳答案

I am pretty much aware we could improve the design, but this is another subject/question/time-hole

因为我怀疑这是你当前问题的原因,也许你不应该忽略它。

我对你的问题的解释是:你有一个外部 AsyncTask(第一个代码 list 中显示的带有 onPublishProgress() 方法的那个)。您正在使用 execute() 执行它。在那个外部 AsyncTask 内部,您有一个内部 AsyncTask(来自您的存储库的那个)。您正在使用 execute() 执行它。而且,您的提示是内部 AsyncTask 在外部 AsyncTask 完成之前不会运行。

如果是这样,您的问题是 execute() 是单线程的,并且您通过让 AsyncTask 无限期运行来占用该线程。在您的外部 AsyncTask 完成其后台工作并从 doInBackground() 返回之前,内部 AsyncTask 会被阻塞。

“我们可以继续使用 hacks 吗?”解决方案是继续使用 AsyncTask 但切换到 executeOnExecutor() 而不是 execute(),提供线程池以供使用。 AsyncTask.THREAD_POOL_EXECUTOR 将成为候选人。

“好的,我们可以稍微清理一下吗?”解决方案是将两个 AsyncTask 实例替换为简单的 Thread 对象或直接使用一些多线程线程池(参见 Executors)。 AsyncTask 已过时,但就其有用性而言,仅当您需要在主应用程序线程 (onPostExecute()) 之后执行工作时才使用它完成后台工作 (doInBackground())。在后台工作完成后,您的 AsyncTask 实现都不需要在主应用程序线程上工作,因此您不需要为它们中的任何一个使用 AsyncTask。因此,例如,您的永久运行线程可以是 Thread,而您在存储库中使用线程池进行 DAO 调用。

(“嘿,我们可以在我们的线程上获得现代性,以配合我们对架构组件的使用吗?”解决方案是切换到 RxJava 或 Kotlin 协程,与 LiveData 结合 — 这需要做更多的工作,但与手动线程管理相比,它们各有千秋)

关于java - 为什么 android room 在生成它的异步任务(对象)的末尾插入一个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56925708/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com