整个应用程序生命周期中的getWritableDatabase()实例

时间:2017-07-27 06:43:23

标签: android multithreading sqlite sqliteopenhelper android-intentservice

我已经使Singelton对象向SQLiteOpenHelper发出查询,其中我保存了getWriteableDatabase()的实例。在整个应用程序生命周期中,对于所有selectinsert/update个查询,我正在使用来自多个IntentService的该实例。我已经阅读了预写日志记录(WAL),它支持并发执行查询。我使用上面的实例禁用WAL。实际上在某个时刻数据库没有返回数据,我想知道SQLite文件是否可以被破坏,因为我使用getWritableabledatabse来从多个意图服务进行读/写。

这种方法会发生僵局吗?

根据我的发现,如果您从多个线程访问数据库,则应启用WAL。

修改

DatabaseAdapter.java

public class DatabaseAdapter {
    private Context mContext;
    private SQLiteDatabase mSqLiteDatabase;
    private DatabaseHelper mDbHelper;
    private static DatabaseAdapter adapter;

    public static DatabaseAdapter getInstance() {
        if(adapter == null) {
            synchronized (DatabaseAdapter.class) {
                if(adapter == null)
                    adapter = new DatabaseAdapter(MyApp.getInstance());
            }
        }

        return adapter;
    }

    public DatabaseHelper getDatabaseHelper() {
        return mDbHelper;
    }

    private DatabaseAdapter(Context c) {
        mContext = c;
        mDbHelper = new DatabaseHelper(mContext);
        mSqLiteDatabase = mDbHelper.getWritableDatabase();
    }

    private long insert(String tableName, ContentValues contentValues) throws Exception {
        this.open();
        long id = mSqLiteDatabase.insert(tableName, null, contentValues);
        this.close();
        return id;
    }

    private int update(String tableName, ContentValues contentValues, int pk_id) throws Exception {
        this.open();
        String whereClause = mDbHelper.pk_id + " = " + pk_id;
        int n = mSqLiteDatabase.update(tableName, contentValues, whereClause, null);
        this.close();
        return n;
    }

    private ArrayList<MyObject> selectChallans(String whereClause, String orderby) throws Exception {
        try {
            ArrayList<MyObject> arrayListObjects = new ArrayList<MyObject>();
            Cursor queryCursor = mSqLiteDatabase.query(tableName, null, whereClause, null, null, null, orderby, null);
            if (queryCursor == null) {
                return null;
            }
            while (queryCursor.moveToNext()) {
                MyObject myobject = getMyObject(queryCursor);
                if(myobject != null)
                    arrayListObjects.add(myobject);
            }
            queryCursor.close();
            return arrayListObjects;
        } catch (Exception e) {
            e.printStackTrace();
            this.forceClose();
            throw e;
        }
    }
}

我通过应用程序使用此Adapter单例实例进行插入/更新和选择查询。我担心mSqLiteDatabase实例。这些函数是从多个IntentService调用的。

1 个答案:

答案 0 :(得分:1)

AFAIK,最佳做法是仅使用一个getWritableabledatabse致电SQLiteOpenHelper一次。之后,您可以将返回的database用于所有线程,而不会出现任何问题。您必须确保使用一个数据库连接。您可以查看Good Answer以获取更多详细信息。

  

SqliteOpenHelper对象保留一个数据库连接。它似乎为您提供读写连接,但它确实没有。调用只读,无论如何都将获得写数据库连接。

     

所以,一个帮助器实例,一个数据库连接。即使您从多个线程使用它,一次一个连接。 SqliteDatabase对象使用java锁来保持序列化访问。因此,如果100个线程有一个数据库实例,则对实际磁盘数据库的调用将被序列化。

     

所以,一个帮助器,一个db连接,在java代码中序列化。一个线程,1000个线程,如果您使用它们之间共享的一个帮助程序实例,则所有数据库访问代码都是串行的。生活是美好的(ish)。

对我来说,我通常在SQLiteOpenHelper课程中创建并打开Application,然后我可以在我的应用程序的任何线程中随处使用它。