【问题标题】:Is it safe to access a SQLite virtual table from UI thread on android?从android上的UI线程访问SQLite虚拟表是否安全?
【发布时间】:2016-07-28 04:14:08
【问题描述】:

我需要维护一个字符串列的数据表,并为所有列启用全文搜索。

我从 Android 文档中了解到:

虚拟表的行为类似于 SQLite 表,但通过回调而不是数据库文件来读取和写入内存中的对象。

是否可以安全地使用 SQLite 虚拟表并从 android 上的主 UI 线程访问该表而不会获得 ANR?

或者我应该选择第三方选项之一,例如:

https://code.google.com/archive/p/multiindexcontainer/

https://github.com/npgall/cqengine

【问题讨论】:

    标签: android sqlite virtual android-anr-dialog


    【解决方案1】:

    来自The Virtual Table Mechanism Of SQLite

    从 SQL 语句的角度来看,虚拟表对象看起来像任何其他表或视图。

    但在幕后,对虚拟表的查询和更新会调用虚拟表对象的回调方法,而不是读取和写入数据库文件。

    因此,从 Android 的角度来看,SQLite 虚拟表的行为与任何其他表或视图完全相同,并且根据 the documentation about ANRs

    (...)

    在任何情况下,您的应用程序可能执行冗长的操作,您不应在 UI 线程上执行工作,而应创建一个工作线程并在那里完成大部分工作。这使 UI 线程(驱动用户界面事件循环)保持运行,并防止系统断定您的代码已冻结。因为这种线程通常是在类级别完成的,所以您可以将响应性视为一个类问题。 (将此与基本代码性能进行比较,这是一个方法级别的问题。)

    在 Android 中,应用程序的响应由活动管理器和窗口管理器系统服务监控。 当检测到以下情况之一时,Android 将显示特定应用程序的 ANR 对话框:

    • 在 5 秒内没有响应输入事件(例如按键或屏幕触摸事件)。

    • BroadcastReceiver 未在 10 秒内完成执行。

    所以,答案是否定的。如果要避免 ANR,从主线程访问 SQLite 虚拟表是不安全的。您可以使用AsyncTasks 访问您的数据库。

    来自 cmets 的更新:

    虽然从 SQLite 的角度来看,整个表都在内存中,但从 Android 的角度来看,系统需要访问数据库,这可能会导致性能问题,例如,如果表足够大,或者取决于实现,

    因为它们可以长时间运行,请确保在后台线程中调用 getWritableDatabase() 或 getReadableDatabase(),例如使用 AsyncTask 或 IntentService

    (来自Saving Data in SQL Databases

    @Chebyr 使用通过 5 个游标连接形成的 5000 行和 15 个字符串列的表充当内存缓存以实现快速访问,并为过滤操作编制索引。因此,假设字符串是 7 个字符长的中等长度,它将大约为 500KB,不会非常消耗内存(取决于索引解决方案的实现),并且我不希望使用索引访问它非常耗时。如果数据是静态的,我会尝试使用@Chebyr 提出的解决方案之一并测量时间和内存(我刚刚使用纯 Java 示例测试了 CQEngine,看起来很有希望)。

    另外,Best practice for keeping data in memory and database at same time on Android 也会有所帮助。

    【讨论】:

    • 由于没有真正的磁盘访问并且整个表都在内存中,什么会导致潜在的冗长操作?
    • 从 SQLite 角度来看,整个表在内存中,但从 Android 角度来看,系统需要访问数据库。例如,如果表足够大,可能会导致冗长的操作。此外,根据您的实现,因为它们可以长时间运行,请确保您在后台线程中调用 getWritableDatabase() 或 getReadableDatabase(),例如使用 AsyncTask 或 IntentService(来自 developer.android.com/intl/es/training/basics/data-storage/… )
    • 这回答了问题的第一部分。那么对于为所有列启用全文搜索的字符串列数据表,您建议使用哪种替代代码模式?
    • 我建议(我回答的最后一句,如果需要我再详细一点,请告诉我)使用AsyncTask在后台执行数据库相关操作并将结果发布到UI 线程 (developer.android.com/intl/es/reference/android/os/…)
    • 我的意思是你建议用什么替代 SQLite 虚拟表作为在支持全文搜索的主线程上使用的数据结构?
    猜你喜欢
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多