并发写入android数据库(从多个服务)? [英] Concurrent writing to android database (from multiple services)?

查看:88
本文介绍了并发写入android数据库(从多个服务)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在android sqlite数据库和并发写入方面遇到了严重问题.为了获得更好的解释,我将为您提供一个真实的例子:

I've a serious problem with android sqlite database and concurrent writing. For better explanations, I will give you a real life example:

我有一个桌面小部件,其中显示了数据库中的项目列表(在后台有DataService,它会定期从远程服务器收集新数据,并使用它们更新数据库).所以-当我单击列表中的某个项目时,我需要更新数据库中被单击的项目(=执行写操作).但是当我恰好单击项目时,当DataService更新数据库中的新数据时,它当然会记录如下错误:

I've an desktop widget, where I'm showing a list of items from my database (and on background I have DataService, which in regular intervals collects fresh data from my remote server, and update my database with them). So - when i click on some item in list, i need to update clicked item (=do write operation) in database. BUT when i click on item exactly in moment, when DataService is updating fresh data in my database, it of course logs an error like this:

android.database.sqlite.SQLiteException: error code 5: database is locked

通常很难模拟,但是如果您安排DataService例如每10秒运行一次(仅用于演示),则您可以非常轻松地模拟此错误.

Normally its hard to simulate, but if u schedule DataService to run for example every 10 seconds (just for demonstration), u can simulate this error very easily.

我的问题是,如何处理?我在文档中读到,如果同时存在两个写入事件,则只有第一个会被执行,第二个会被记录为错误.听起来很奇怪,必须有其他选择,例如第二次写入将等到第一次写入完成.还是其他解决方案?试图阅读文档,但似乎该文档在google文档中涵盖的不是很好...我所拥有的几乎所有信息,都是在官方页面以外的地方找到的.

And my question is, how to handle this? I read in docs, that if there are two write events in same time, only first will be executed, second will be logged as an error. Its sounds strange, there must be another options, for example the second write would wait until first write finish. Or maybe other solution? Trying to read docs, but it seems, that this item is not very good covered in google docs...Almost every info I have, I found on other than official pages.

PS:这是我的DBHelper类的简化版本:

PS: This is my shortened version of my DBHelper class:

public class DBHelper extends SQLiteOpenHelper {

    private static final String TABLE_NEWS = "News";    
    private static final String COL_ID = "id";
    private static final String COL_TITLE = "title";
    private static final String COL_ALERT = "alert";

    public DBHelper(Context context) {
        super(context, "MY_DB_NAME", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + TABLE_NEWS + "(" + COL_ID + " TEXT PRIMARY KEY," + COL_TITLE + " TEXT," + COL_ALERT + " INTEGER" + ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NEWS);
        onCreate(db);
    }

    public void addRecords(ArrayList<NewsItem> items) {
        SQLiteDatabase db = this.getWritableDatabase();    
        for (int i = 0; i < items.size(); i++) {
            NewsItem item = items.get(i);    
            ContentValues values = new ContentValues();
            values.put(COL_ID, item.getId());
            values.put(COL_TITLE, item.getTitle());
            values.put(COL_ALERT, item.getAlertMe());    
            db.insert(TABLE_NEWS, null, values);
        }    
        db.close();
    }

    public int updateRecord(NewsItem item) {
        SQLiteDatabase db = this.getWritableDatabase();    
        ContentValues values = new ContentValues();
        values.put(COL_ALERT_ME, item.getAlertMe());
        int updated = db.update(TABLE_NEWS, values, COL_ID + " = ?", new String[] { item.getId() });
        db.close();    
        return updated;
    }
}

推荐答案

您需要在所有线程(及其托管组件)中使用单个SQLiteDatabase对象,以确保线程安全.使您的DBHelper为单身人士,或使用ContentProvider来实现此效果.

You need to use a single SQLiteDatabase object, across all threads (and their hosting components), to get thread safety. Make your DBHelper be a singleton, or use a ContentProvider, to achieve this effect.

这篇关于并发写入android数据库(从多个服务)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆