Is it safe to access a SQLite virtual table from UI thread on android?

时间:2016-04-07 10:30:13

标签: android sqlite virtual android-anr-dialog

I need to maintain a data table of string columns with full text searching enabled for all the columns.

I understand from Android documentation:

A virtual table behaves similarly to a SQLite table, but reads and writes to an object in memory via callbacks, instead of to a database file.

Would it be safe to use a SQLite virtual table for the purpose and access the table from main UI thread on android without getting an ANR?

Or should I go for one of the third party options like:

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

https://github.com/npgall/cqengine

1 个答案:

答案 0 :(得分:1)

来自The Virtual Table Mechanism Of SQLite

  

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

     

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

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

  

(...)

     

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

     

在Android中,应用程序响应性由活动管理器和Window Manager系统服务监视。 Android会在检测到以下某种情况时显示特定应用程序的ANR对话框:

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

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

  •   

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

从评论中更新:

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

  

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

(来自Saving Data in SQL Databases

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

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