在Android应用程序中对SQLite数据库执行查询时,最佳做法是什么?
从AsyncTask的doInBackground运行插入,删除和选择查询是否安全?或者我应该使用UI线程?我认为数据库查询可能"很重",不应该使用UI线程,因为它可以锁定应用程序 - 导致应用程序无响应(ANR).
如果我有几个AsyncTasks,他们应该共享一个连接还是应该分别打开一个连接?
这些方案是否有最佳实践?
我们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)
有没有人有一个代码的一般例子,它从一个读取的不同线程写入数据库,我们如何确保线程安全. …
我有一个功能正常的应用程序,不会强制关闭或崩溃.但是当我看LogCat时,它偶尔会给我这个:
05-20 15:24:55.338: E/SQLiteDatabase(12707): close() was never explicitly called on database '/data/data/com.---.--/databases/debt.db'
05-20 15:24:55.338: E/SQLiteDatabase(12707): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
Run Code Online (Sandbox Code Playgroud)
一点点下来......
05-20 15:24:55.338: E/System(12707): Uncaught exception thrown by finalizer
05-20 15:24:55.338: E/System(12707): java.lang.IllegalStateException: Don't have database lock!
Run Code Online (Sandbox Code Playgroud)
我不确定何时应该打开和关闭我的数据库?
我有一个主要活动,只是一个闪屏.然后它进入一个使用来自DB的信息调用ListView的活动; 所以在这个 DB首次打开的活动中.
还有一个其他活动,其中需要DB与ListVeew分支.什么时候我应该打开和关闭这个?Word似乎是我只需要打开一次,然后在应用程序"暂停","停止"或"销毁"时关闭.
如果是这种情况,我在哪里将db.close()方法放在启动屏幕主要活动中,其中onStop等位于何处?或者与打开数据库的活动相同的活动?或..还有另一个地方吗?
更新:
这是错误指向的代码行:
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
Run Code Online (Sandbox Code Playgroud) 所以我想出了一些想法,我想知道它是否可以实现.
假设我有多个表(数据库模型),每个表都由某个类表示.我不会使用单一模式和open helper,所以我创建了一个简单的类来提供数据库的单个实例.我我们的想法是,只要所有表都引用SQLiteDatabase(由open helper返回),它们都将使用相同的数据库实例,并且可能不需要将工作与数据库同步,因为open helper执行此操作.当最后一个表完成它的工作GC将收集打开的帮助器(因为最后一个引用将是弱引用) - >调用finalize()并在此方法期间关闭db以防止来自OS的任何警告.我的问题是:这可以工作吗?它会自动关闭数据库,它会泄漏还是抛出一些异常?
这是我的班级:
public class DatabaseHelper {
private static WeakReference<SomeCustomOpenHelper> sDBOpenHelper;
private void notifyDBCreate(SQLiteDatabase db) {
for (DBTable table : mTables) {
table.onDBCreate(db);
}
}
private void notifyDBUpgrade(SQLiteDatabase db) {
for (DBTable table : mTables) {
table.onDBUpgrade(db);
}
}
public SQLiteDatabase getDatabase(boolean readOnly) {
SomeCustomOpenHelper dbHelper = sDBOpenHelper.get();
if (dbHelper == null) {
dbHelper = new SomeCustomOpenHelper(context, name, factory, version, new DatabaseEventsCallback());
sDBOpenHelper = new WeakReference<SomeCustomOpenHelper>(dbHelper);
}
if (readOnly) {
return dbHelper.getReadableDatabase();
} else { …Run Code Online (Sandbox Code Playgroud) 我正在编写一个具有"在线模式"的应用程序,即根据需要下载,解析数据并将其插入到SQLite数据库中.所有这些都是由服务完成的.该应用程序包含几个要求服务进行数据更新的活动(根据活动的不同数据).
当用户浏览活动时(无需等待服务完成),很容易获得SQLiteExceptions(消息:数据库被锁定).
我考虑过使用synchronized块,但这会强制用户在服务完成更新时加载新活动(需要加载数据库访问权限)时等待.所以这似乎是一个死胡同.
另一种选择可能是在每个活动的onStop方法中停止更新.当然,更新将被中断,但这不是一个大问题.问题在于我不确定如何处理它.
我的问题是,我该怎样/应该如何处理?
我在Android上使用SQLite时遇到问题.我能够解析XML文件,然后创建一个数据库来存储内容.创作,插入工作正常.我可以在文件资源管理器中看到.db文件
我最后一次调用checkDataBase()会返回false?为什么?
我正在使用模拟器上的Android 2.3.
难道我做错了什么 ?
活动:
public class MTGDBActivity extends Activity{
String currentDBPath = "data/data/rudy.jaumain.mtgdb/databases/MTGCards";
MTGContainerData mtgcd;
MTGDatabase mtgdb;
Button buttonEditions, buttonCollection, buttonDecks;
View v;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
this.mtgcd = new MTGContainerData(this);
if (!this.checkDataBase()) {
System.out.println("FILE DOESN'T EXIST");
this.mtgdb = new MTGDatabase(this);
this.mtgdb.open();
this.mtgcd.loadCards(this.mtgdb);
System.out.println("CARDS LOADED");
this.mtgdb.close();
}
else{
System.out.println("FILE DOES EXIST");
}
} catch (Exception e) {
System.out.println("FAIL");
}
System.out.println(this.checkDataBase());
this.setContentView(R.layout.main);
this.initialize();
} …Run Code Online (Sandbox Code Playgroud)