如何解决无论实际查询花费多长时间,rawQuery总是立即执行
我已经花了好几个小时试图了解为什么一个简单明了的Android代码破坏了我应用程序中的基本同步。
下面的方法总是立即执行,尽管事实上它有一个sqliteDatabase.rawQuery()调用。 SQL查询花费多长时间都没关系:
// this method is always executed instantly,despite the rawQuery() call
private Cursor runRawQuerytest() {
Log.i(TAG,"runRawQuerytest() started");
long timer = System.currentTimeMillis();
// SLOW_sql_QUERY runs at least a couple seconds:
Cursor c = getDb().rawQuery( SLOW_sql_QUERY,null );
timer = System.currentTimeMillis() - timer;
// timer below always reports a few milliseconds:
Log.i(TAG,"runRawQuerytest() finished in " + timer + "ms.");
return c;
}
这是Logcat:
2020-10-06 23:57:07.609 ... I/MainActivity: runRawQuerytest() started
2020-10-06 23:57:07.621 ... I/MainActivity: runRawQuerytest() finished in 12ms. <<<< "incorrect" timer
好像以某种方式内联了runRawQueryTest()方法。它本身不是问题(无论如何,谁在乎日志?),因为数据库查询实际上发生在调用runRawQueryTest()的方法中:
public void onClick(View view) {
long timer = System.currentTimeMillis();
Log.i(TAG,"onClick()" );
Cursor c = runRawQuerytest();
// database query actually happens here:
Log.i(TAG,"cursor.getCount() " + c.getCount());
if ( !c.isClosed() ) c.close();
timer = System.currentTimeMillis() - timer;
Log.i(TAG,"onClick() - done in " + timer + "ms. ");
}
Logcat:
2020-10-06 23:57:07.609 ... I/MainActivity: onClick()
2020-10-06 23:57:07.609 ... I/MainActivity: runRawQuerytest() started
2020-10-06 23:57:07.621 ... I/MainActivity: runRawQuerytest() finished in 12ms.
2020-10-06 23:57:14.223 ... I/MainActivity: cursor.getCount() 1 <<<< actual query
2020-10-06 23:57:14.223 ... I/MainActivity: onClick() - done in 6614ms. <<<< correct timer
真正的问题是,在我的应用程序中,这些数据库调用是使用RxJava异步进行的。 rawQuery()包装在Observable中,如下所示:
// RxJava wrapper
public Single<Cursor> makeObservable(final String query) {
return Single
.fromCallable( () -> getCursorOrThrow(query) )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
您可能已经猜到了,Observable几乎立即发出一个项目,因此实际的SQL查询在onNext()调用之后运行。结果,主线程上进行了太多工作,UI混乱了,尤其是进度条。
如何确保rawQuery()方法同步执行?
我唯一的猜测是所有这些都是由于非理想的R8优化而发生的。但是我的项目具有非常标准的“开箱即用”设置。我试图解决问题,使用ProGuard的“ -dontoptimize”键并尝试使用不同的Gradle版本。不幸的是,它没有帮助。我的想法不多了。我在概念上做错了吗?非常感谢您的帮助!
要点: https://gist.github.com/DmitryOganezov/c52fd8fcfa4f5be3e6ae5016a6ef7b4d
解决方法
如何确保rawQuery()方法同步执行?
在返回之前,必须getCursorOrThrow()
上getCount()
呼叫Cursor
。
Cursor是SQLiteCursor
,在第一次使用数据时它会懒执行查询。这是“对于当今我们的工作方式非常可怕的非常酷的想法”之一。在后台线程上调用getCount()
会强制SQLiteCursor
实际加载其数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。