我是Android上的新手,我正在开发一个简单的应用程序来获得一些基本的体验.我的应用程序非常简单,包括广播接收器和一些活动.这两个组件都使用单个数据库,因此从理论上讲,两者都可能同时尝试访问数据库.
目前我只是在每次需要时实例化db对象(它是一个SQLite数据库帮助程序类),并执行所需的操作:查询,插入等.
从我在这里和其他一些文档中读到的,这有一个问题是在同时访问db的情况下获得"db locked"异常,所以更好的方法是拥有这个db对象的单个实例所以所有组件始终使用相同的数据库连接.
以上推理是否正确?那么一个单身人士会成为一个足够好的解决方案吗?我知道一些纯粹主义者可能反对它,但请注意,这是一个相当简单的应用程序,所以我可以负担得起在其他情况下我不会做的事情.
否则,更好的选择是什么?我已经阅读过有关使用内容提供商的内容,但这对此来说太过分了,除此之外我对与其他活动共享数据不感兴趣.我确实读过这篇文章,发现它很有帮助.
我收到了以下错误.那么如何解锁我的数据库呢?
10-28 08:43:26.510: ERROR/AndroidRuntime(881): FATAL EXCEPTION: Thread-11
10-28 08:43:26.510: ERROR/AndroidRuntime(881): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:742)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at com.aa.me.vianet.dbAdapter.DbAdapter.open(DbAdapter.java:25)
10-28 08:43:26.510: ERROR/AndroidRuntime(881): at com.aa.me.vianet.services.NotificationManagerThread.run(NotificationManagerThread.java:49)
Run Code Online (Sandbox Code Playgroud) 我有一个包含一些表的数据库.我想使用多个线程更新表.我将在所有线程中使用相同的SQLiteDatabase实例.
请建议这种方法是否正确.Sqlite数据库线程安全吗?两个不同的线程可以同时为不同的值集更新同一个表.
我在我的应用程序中使用了包含多个表的数据库.我有一个XML解析器,需要在解析时将数据写入两个表.我为这两个表创建了两个数据库适配器,但现在我遇到了问题.当我使用一张桌子时,很容易:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
firstTable.open(); // open and close it every time I need to insert something
// may be hundreds of times while parsing
// it opens not a table but whole DB
firstTable.insertItem(Item);
firstTable.close();
Run Code Online (Sandbox Code Playgroud)
因为它是一个SAX解析器,在我看来(也许我错了),这将更好:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
@Override
public void startDocument() throws SAXException
{
firstTable.open(); // open and close only once
}
...
firstTable.insertItem(Item);
...
@Override
public void endDocument() throws SAXException
{
firstTable.close();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我需要将数据插入第二个表,我该怎么做?例如,如果我有第二个适配器,我认为这将是一个坏主意:
FirstDBAdapter firstTable = new FirstDBAdapter(mycontext);
SecondDBAdapter secondTable = …Run Code Online (Sandbox Code Playgroud) 我有一个CursorLoader直接使用SQLite数据库而不是使用的自定义ContentProvider.这个加载器使用a ListFragment支持CursorAdapter.到现在为止还挺好.
为了简化操作,我们假设UI上有一个Delete按钮.当用户单击此按钮时,我会从数据库中删除一行,并调用onContentChanged()我的加载程序.此外,在onLoadFinished()回调时,我调用notifyDatasetChanged()我的适配器以刷新UI.
当删除命令快速连续发生时,意味着快速连续onContentChanged()调用,bindView()最终将使用陈旧数据.这意味着行已被删除,但ListView仍在尝试显示该行.这导致了Cursor异常.
我究竟做错了什么?
这是一个自定义的CursorLoader(基于Diane Hackborn女士的建议)
/**
* An implementation of CursorLoader that works directly with SQLite database
* cursors, and does not require a ContentProvider.
*
*/
public class VideoSqliteCursorLoader extends CursorLoader {
/*
* This field is private in the parent class. Hence, redefining it here.
*/
ForceLoadContentObserver mObserver;
public VideoSqliteCursorLoader(Context context) {
super(context); …Run Code Online (Sandbox Code Playgroud) android asynctaskloader android-loadermanager android-cursorloader android-loader
我已经阅读了很多主题,但无法找出问题的答案:是否可以同时读写?
我有后台线程更新一些数据,UI需要存储在DB中的小块数据.因此在UI线程中执行SELECT操作.但它会在更新过程中阻止.结果,UI冻结了几秒钟.
写作时有没有人能从DB中读取成功?
它可以在iPhone上读写DB.这种差异的原因是在本机sqlite函数上同步实现包装吗?
如果您只是从不关闭连接会发生什么?我知道如果你不关闭它并尝试打开另一个,你会得到例外,但是如果你有一个全局单例,你只是不关闭它会发生什么?任何的想法?
我最近更新了我的一个(开源)Android应用程序,我的用户正在获得一个我无法复制的例外.关键部分是:
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
然后
Caused by: android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/com.airlocksoftware.hackernews/databases/hacker_news_cache.db' to 'en_US'.
这种情况发生在使用Android 2.3 - 4.2.1的设备上,并且在我尝试连接数据库的应用程序中的多个位置.我使用它后关闭数据库.
我找不到有关"未能更改db语言环境"异常的更多信息.当我查看SQLiteConnection的源代码(第386行)时,它似乎是'android_metadata'表或'使用新的语言环境更新索引'的问题.
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856) Caused by: android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/com.airlocksoftware.hackernews/databases/hacker_news_cache.db' to 'en_US'.
at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:386)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at …Run Code Online (Sandbox Code Playgroud) Android文档说
可以从不同进程和线程中的各种ContentResolver对象调用ContentProvider方法,它们必须以线程安全的方式实现
我在Stackoverflow上发现了这篇文章 - sqlite内容提供程序和多线程 ,它说它已经是线程安全了吗?
那么,只是想知道如何创建一个线程安全的ContentProvider?如果我进行插入/更新/删除方法就足够了syncronized
public synchronized Uri insert (Uri uri, ContentValues values) {
}
Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我必须实现一些UI和同步服务.它在后台运行并更新数据.同步服务不是很简单,它使用多线程.
所以,这是我的故事:当我开始开发这个应用程序时,我对sqlite一无所知,所以我只是没有在Java中使用任何线程同步.结果:我得到了许多异常,例如"SQLiteException:数据库被锁定:BEGIN EXCLUSIVE;"
然后我将所有事务与常规Java synchronized(){}块同步.一切都好得多了.但我使用Cursors为我的列表实现CursorAdapter.所以,有时我得到相同的"SQLiteException:数据库被锁定:BEGIN EXCLUSIVE;"
我结束了创建一个小线程安全的sqlite实用程序,它处理所有线程安全的东西.另外,我必须使用像ArrayAdapter这样的东西(从Cursor读取所有数据并在读取后关闭它,同时也同步这个块).所以,它运作正常
但是,我不喜欢这种处理UI的方式,因为这个解决方案让UI变得非常慢 - 从光标读取一些数据相当快,但比使用CursorAdapter慢
那么,谁得到了这个问题的解决方案?谢谢