在Android应用程序中对SQLite数据库执行查询时,最佳做法是什么?
从AsyncTask的doInBackground运行插入,删除和选择查询是否安全?或者我应该使用UI线程?我认为数据库查询可能"很重",不应该使用UI线程,因为它可以锁定应用程序 - 导致应用程序无响应(ANR).
如果我有几个AsyncTasks,他们应该共享一个连接还是应该分别打开一个连接?
这些方案是否有最佳实践?
我正在阅读有关此问题的stackoverflow,但我仍然没有找到解决方案.我注意到有时,我的应用程序会抛出此错误:
java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
...
Run Code Online (Sandbox Code Playgroud)
我有一个名为DatabaseHelper.java的文件,使用这种方法获取它的实例:
public static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
Run Code Online (Sandbox Code Playgroud)
然后我有像这样的方法(它在行cursor.moveToFirst()中崩溃与该错误).它几乎从不崩溃,但有时它会崩溃.
public Profile getProfile(long id) {
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_PROFILES + " WHERE " + KEY_PROFILES_ID + " = " + id;
Cursor cursor = db.rawQuery(selectQuery, null);
// looping …Run Code Online (Sandbox Code Playgroud) 我们AsyncTasks用来访问数据库表和游标.
不幸的是,我们偶尔会看到有关数据库被锁定的例外情况.
E/SQLiteOpenHelper(15963): Couldn't open iviewnews.db for writing (will try read-only):
E/SQLiteOpenHelper(15963): android.database.sqlite.SQLiteException: database is locked
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1637)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1587)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:638)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:659)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:652)
E/SQLiteOpenHelper(15963): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:482)
E/SQLiteOpenHelper(15963): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
E/SQLiteOpenHelper(15963): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)
E/SQLiteOpenHelper(15963): at com.iview.android.widget.IViewNewsTopStoryWidget.initData(IViewNewsTopStoryWidget.java:73)
E/SQLiteOpenHelper(15963): at com.iview.android.widget.IViewNewsTopStoryWidget.updateNewsWidgets(IViewNewsTopStoryWidget.java:121)
E/SQLiteOpenHelper(15963): at com.iview.android.async.GetNewsTask.doInBackground(GetNewsTask.java:338)
E/SQLiteOpenHelper(15963): at com.iview.android.async.GetNewsTask.doInBackground(GetNewsTask.java:1)
E/SQLiteOpenHelper(15963): at android.os.AsyncTask$2.call(AsyncTask.java:185)
E/SQLiteOpenHelper(15963): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
E/SQLiteOpenHelper(15963): at java.util.concurrent.FutureTask.run(FutureTask.java:122)
E/SQLiteOpenHelper(15963): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
E/SQLiteOpenHelper(15963): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
E/SQLiteOpenHelper(15963): at java.lang.Thread.run(Thread.java:1060)
Run Code Online (Sandbox Code Playgroud)
有没有人有一个代码的一般例子,它从一个读取的不同线程写入数据库,我们如何确保线程安全. …
我使用此类来管理与底层SQLiteDatabase的连接
public class BasicDataSource {
protected DatabaseHandler dbHelper;
protected volatile SQLiteDatabase readable_database;
protected volatile SQLiteDatabase writable_database;
protected Object read_lock = new Object();
protected Object write_lock = new Object();
protected Context context;
protected BasicDataSource(Context ctx) {
dbHelper = DatabaseHandler.getInstance(ctx);
getReadableDatabase();
dbHelper.onCreate(getWritableDatabase());
this.context = ctx;
}
public synchronized void close() {
dbHelper.close();
}
protected void closeInsertHelpers(InsertHelper... helpers) {
for (InsertHelper ih : helpers) {
if (ih != null)
ih.close();
}
}
protected SQLiteDatabase getReadableDatabase() {
synchronized (read_lock) {
if (readable_database == null …Run Code Online (Sandbox Code Playgroud)