Android 数据库的sigleton实例在类中而不是在方法中给出数据库锁定异常

Android 数据库的sigleton实例在类中而不是在方法中给出数据库锁定异常,android,singleton,android-sqlite,database-locking,Android,Singleton,Android Sqlite,Database Locking,当我在类中使用singleton数据库对象时,我遇到了一个问题,在类中我得到了数据库锁定异常,但是当我在同一类的任何方法中使用相同的对象时,一切都很好,我对行为感到困惑。下面是代码:数据库类:具有单例功能 public class Database extends SQLiteOpenHelper{ private static String dbname="Director"; private static int dbversion=1;

当我在类中使用singleton数据库对象时,我遇到了一个问题,在类中我得到了数据库锁定异常,但是当我在同一类的任何方法中使用相同的对象时,一切都很好,我对行为感到困惑。下面是代码:数据库类:具有单例功能

public class Database extends SQLiteOpenHelper{

        private static  String dbname="Director";
        private static int dbversion=1;
        SQLiteDatabase db;
        private Context m1Context;
        private static Database minstance;
        public Database(Context context) {

            super(context, dbname, null, dbversion);
            // TODO Auto-generated constructor stub

        }

        public synchronized static Database getInstance(Context m1Context){

            if (minstance==null){

            minstance=new Database(m1Context);
            }
            return minstance;


        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            // TODO Auto-generated method stub

            STable st=new StockTable(m1Context);
            BTable bt=new BrokerageTable(m1Context);
            SList sl=new StockList(m1Context);

            db.execSQL(st.stocktable);
            db.execSQL(bt.Brokerage);
            db.execSQL(sl.Create());
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub

        }


    }
现在,当我在多个类中使用singleton实例时,只有当它在类内声明,而不是在同一类的方法内声明时,才会锁定错误数据库。在下面的代码行中,astrik和加号之间的代码行给出了类内的错误,加号和加号之间的代码行并没有给出错误,但我在这两种情况下都做了相同的处理

public class SList {

    Context c1;
    Cursor getid;
    StockList(Context mContext){

        c1=mContext;
    }

    **//SQLiteDatabase sd=Database.getInstance(c1).getWritableDatabase();**
    String Ctable;
    //String ,selectIDgetstocks,deletestock;
    public String tablename="Stocklist";
    public String Column1="_id";
    public String Column2="Sname";
    ContentValues cv=new ContentValues();
    String getstocks="Select " + Column1 + " as _id, " + Column2 + " From "+ tablename;
    String selectID="Select Max("+  Column1 + ") from " + tablename;
    public String Create(){

        Ctable="Create Table " + tablename + " (" + Column1 + " INTEGER PRIMARY KEY , " + Column2 + " Text" + ")";

        return Ctable;
    }

    public void insert(int stockid,String name){

        cv.put(Column1, stockid);
        cv.put(Column2, name);
    ++Database.getInstance(c1).getWritableDatabase().insert(tablename,null,cv);++

    }


}
有人能帮我澄清一下我的困惑吗?如果可能的话,让我知道单例使用的功能。我的想法是在类开始时在数据库变量中使用sigleton实例,并在整个类中需要的地方使用该变量,但这是不可能的,不知道为什么,但当我在所有位置使用同一实例时,则不会出错


请帮助我理解。

如果您使用数据库,请使用此

String query = "select * from table1";
synchronized(Database.getInstance(c1) )
        {
           db = Database.getInstance(c1).getWritableDatabase();
           Cursor c = db.rawQuery( query );
           c.moveToFirst();
           do
           {
                // do someting use database.
                Log.d( SList.class.getName(), c.getString( 0 ) );
           }while( c.moveToNext() );
           c.close();
           db.close();
        }

如果使用完db,是否调用db close?若你们得到Instance调用GetWritableDatabase,另一个地方同时调用GetWritableDatabase,你们可能会得到错误。实例,即getWratableDatabase,您稍后调用,并提前关闭。感谢您的回复。。。我没有调用db.close,但我有5个活动,在所有活动中,我需要getwritabledatabase实例。。。但是在这种情况下,我如何实现功能,以及我应该在哪里调用db.close,就好像在一个活动数据库使用完成后,另一个活动数据库使用开始一样。对不起,我不太清楚您的问题。现在,我明白了。很简单。你只需要使用synchronized。本页的答案是“帮助您”。[链接]Singleton与synchronized不同。单例模式只是生成一个实例,比如static(但它有些不同)。synchronized是多线程中的安全实例。它是做相同的函数互斥或信号量(但显然不一样。)感谢链接,但为什么我在类的开头声明它会给我错误,在语句中使用它不会给我数据库锁定异常?另外,请您解释如何以及何时关闭数据库对象。谢谢您的回答。。这里我有一个问题
Database.getInstance(c1).getWritableDatabase()如果我对多个查询(如insert、select、delete)多次使用此语句,会对数据库产生任何影响吗?。还需要在每次操作(插入、选择或删除)后关闭数据库…感谢您的持续协助,只要数据发生更改(插入或删除),它就会对数据库产生影响。如果你想及时进行多次手术,只需在手术结束后进行。如果使用游标,请在使用完游标后关闭数据库。您可以在android sqlite3中使用事务。如果您想要交易,此链接将帮助您。[链接]如果您这样做,它可能是一个例外。首先,插入数据。其次,使用execSql选择并连接游标。第三,从数据库中删除数据wehre在游标中。然后,当您第二次得到游标时,使用游标的数据(getString、getInt等),它可能是异常的。游标不是用来存储数据的。只是连接数据库的数据。对不起,我的英语不是很好,所以我的答案很难理解。但我试着解释我所知道的。没问题@Amadas。。。你确实帮助了我。。。一旦我在代码中实现您的建议,我将接受答案。