Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/199.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android SQLite异常:数据库被锁定问题_Android_Sqlite_Exception_Locking - Fatal编程技术网

Android SQLite异常:数据库被锁定问题

Android SQLite异常:数据库被锁定问题,android,sqlite,exception,locking,Android,Sqlite,Exception,Locking,我的SQLite数据库在Android应用程序中出现问题。这种情况似乎经常发生,我无法重现,但这是安卓市场给出的报告 基本上,我首先有一个启动屏幕活动,首先检查数据库中是否有所有需要的数据。如果没有,它将在异步线程中安装数据并关闭数据库连接 然后,也只有到那时,主活动才能启动,它还可以打开并读取/写入数据库 此代码通过启动屏幕活动的onCreate方法执行: dbWord = new WordDBAdapter(this, myUI); dbWord.open(); if (dbWord.isD

我的SQLite数据库在Android应用程序中出现问题。这种情况似乎经常发生,我无法重现,但这是安卓市场给出的报告

基本上,我首先有一个启动屏幕活动,首先检查数据库中是否有所有需要的数据。如果没有,它将在异步线程中安装数据并关闭数据库连接

然后,也只有到那时,主活动才能启动,它还可以打开并读取/写入数据库

此代码通过启动屏幕活动的onCreate方法执行:

dbWord = new WordDBAdapter(this, myUI);
dbWord.open();
if (dbWord.isDataInstalled()) {
    dbWord.close();
    databaseInstalled = true;
    clickToStartView.setText(myUI.PRESS_TO_START);
    clickToStartView.startAnimation(myBlinkAnim);
} else {
    // If not, try to install in asynchronous thread
    progressDialog = new ProgressDialog(this);
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    progressDialog.setMessage(myUI.INSTALLING_DB);
    progressDialog.setCancelable(false);
    new InstallDBData().execute("");
}
public class WordDBAdapter {
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;

    public WordDBAdapter open() throws android.database.SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        mDbHelper.close();
    }
    ...
}
异步线程的代码为:

private class InstallDBData extends AsyncTask<String, Integer, Integer> {

    @Override
    protected Integer doInBackground(String... arg0) {
        progressDialog.setProgress(0);
        dbWord.installData(0, getApplicationContext());
        progressDialog.setProgress(20);
        dbWord.installData(1, getApplicationContext());
        progressDialog.setProgress(40);
        dbWord.installData(2, getApplicationContext());
        progressDialog.setProgress(60);
        dbWord.installData(3, getApplicationContext());
        progressDialog.setProgress(80);
        dbWord.installData(4, getApplicationContext());
        progressDialog.setProgress(100);
        return 1;
    }

    protected void onPreExecute() {
        progressDialog.show();
    }

    protected void onPostExecute(Integer x) {
        dbWord.close();
        progressDialog.hide();
        databaseInstalled = true;
        clickToStartView.setText(myUI.PRESS_TO_START);
        clickToStartView.startAnimation(myBlinkAnim);
    }
}
我得到了以下异常,它们类似,但有不同的信息:

第一类错误消息:

java.lang.RuntimeException: Unable to start activity 
  ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}: 
  android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1830)
....
Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1870)
at android.database.sqlite.SQLiteDatabase.beginTransactionWithListener(SQLiteDatabase.java:602)
第二类错误消息:

java.lang.RuntimeException: Unable to start activity 
  ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}: 
  android.database.sqlite.SQLiteException: database is locked
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
....
Caused by: android.database.sqlite.SQLiteException: database is locked
at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987)
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1855)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
java.lang.RuntimeException:无法启动活动
ComponentInfo{example.flashcards.medical/com.example.flashcards.common.SplashWindow}:
android.database.sqlite.SQLiteException:数据库已锁定
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)上
在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)上
....
原因:android.database.sqlite.SQLiteException:数据库已锁定
位于android.database.sqlite.SQLiteDatabase.native_setLocale(本机方法)
位于android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1987)
位于android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1855)
位于android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:820)
位于android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:854)
我真的不想创建一个ContentProvider,因为我认为如果有一个更简单的解决方案可用,那就太过分了。此外,只有此应用程序可以访问数据库


关于如何解决这个问题有什么建议吗?

可能是因为您没有正确打开或创建数据库。如果是这样的话,试试看

mDb = mCtx.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null);
在DatabaseHelper类中:

public DatabaseHelper(Context aContext)
{       
    mDb = aContext.openOrCreateDatabase(DatabaseName, SQLiteDatabase.CREATE_IF_NECESSARY, null);    
    OpenHelper openHelper = new OpenHelper(aContext, mDb );     
    mDb = openHelper.getWritableDatabase();
}

我建议您在主线程中关闭DB,并在doInBackground方法中打开和关闭它:

    @Override
    protected Integer doInBackground(String... arg0)
    {
        db.open();
        try {
        // your code here
        } finally {
            db.close()
        }            
        return 1;
    }

另外,您不应该直接从AsyncTask调用UI方法,因为UI不是线程安全的。相反,从doInBackground调用方法updateprogressprogress,并在从主线程调用onProgressUpdate时从onProgressUpdate更新progressDialog

在做了一些努力之后,我做到了(我的应用程序在安卓2.3之前一直运行得很完美,但当我在蜂窝平板电脑上运行它时,出现了db锁错误)。
我确实使用了信号量(在关键部分使用锁)

示例1

public class DbExp extends SQLiteOpenHelper{
    public static String Lock = "dblock";
    private static final String DATABASE_NAME = "db.db";
    private static final String TABLE_NAME = "table_name";

    public void delete(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = getWritableDatabase();
            db.delete(TABLE_NAME, null, null);
            db.close();
        }
    }

    public void insert(){
        synchronized(Lock) {
            SQLiteDatabase db  = getWritableDatabase();
            db.insert(TABLE_NAME, ..., ...);
            db.close();
        }
    }

}
示例2

public class DB {
    public static String Lock = "dblock";
    private static final String DATABASE_NAME = "db.db";
    private static final String TABLE_NAME = "table_name";

    public void delete(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
            db.delete(TABLE_NAME, null, null);
            db.close();
        }
    }

    public void insert(Context mContext){
        synchronized(Lock) {
            SQLiteDatabase db  = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
            db.insert(TABLE_NAME, ..., ...);
            db.close();
        }
    }


}

希望这对将来的任何人都有帮助:)

如果您使用片段,并且发生了方向更改,这是因为您有两个相同片段的实例,并且它们都有自己的某种Db helper类实例。为了使它能够工作,您必须在方向更改时销毁片段并重建它,或者找到一种方法来销毁Db helper类。这仅适用于存在方向问题的片段。我不得不做了大量的故障排除来解决这个问题,所以希望有人觉得这个问题很有帮助

看起来这是一个老问题,但也许这会帮助一些人。我也遇到了同样的问题,我可能在一个数据库中加载了十几个表,并且经常崩溃,不总是,但有时会

最后,这可能是hackey,我只是为每个表创建了一个单独的数据库。现在我有十几个数据库,每个数据库有一个表。但是,没有其他例外。代码是声音,正确地创建、打开和关闭,似乎在某个地方发生了碰撞

就像我说的,你可以认为它是哈基,但它解决了我的问题。
sqlDB.endTransaction();

db

这就是我的原因:

在插入db之后,我忘记了在函数调用中结束事务。所以当我尝试插入另一个活动的另一条记录时,我得到了数据库锁定异常。添加以下语句解决了我的问题

sqlDB.endTransaction();

这些代码行解决了我的(相同)问题:

(我的交易在……之前被打开过)


这会去哪里?在public WordDBAdapter open()内部?我已经在DatabaseHelper类的构造函数中完成了。我为你编辑我的答案。你确定这是必要的吗?根据Android文档中关于SQLiteOpenHelper的内容:“您创建了一个子类,实现onCreate(SQLiteDatabase)、onUpgrade(SQLiteDatabase、int、int)和onOpen(SQLiteDatabase),该类负责打开数据库(如果存在),创建数据库(如果不存在),并根据需要进行升级。事务用于确保数据库始终处于合理状态。“我的DatabaseHelper类扩展了SQLiteOpenHelper,因此应涵盖打开和创建数据库(如果需要),对吗?Khawar,我注意到你没有调用super(context,DATABASE\u NAME,null,DATABASE\u VERSION)) constructor@Khawar不介意我用这种方式访问应用程序数据库,但在我的情况下不起作用请看一下我的问题请注意,使用这种方法,您将无法在单独的数据库中创建涉及表的事务。使用每个表一个数据库会破坏建立关系数据库的许多目的,例如执行联接或跨多个表进行事务处理。太棒了。我已经花了好几个小时研究这个。。。你救了我一天,兄弟。