Насколько я должен быть осторожен с безопасностью потоков при создании методов / действий, которые взаимодействуют с базой данных SQLite? - PullRequest
7 голосов
/ 21 сентября 2010

Я создаю приложение, которое позволяет запускать множество различных Activities с TabActivity (до ~ 25).Для большинства действий требуются данные из базы данных sqlite, поэтому при запуске onCreate AsyncTask создает объект SQLiteOpenHelper (который откроет базу данных для чтения / записи), запускает запрос, данные извлекаются, и всезакрыто.

Я просто тестировал игру, чтобы посмотреть, смогу ли я что-нибудь сломать, поэтому я добавлял каждые Activity к TabActivity's TabHost.Затем я начал растирать каждую вкладку как можно быстрее.

я заметил, что очень быстро я начал видеть в LogCat: Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;, и приложение продолжало умирать.

Как правило, будет только около 4-6 вкладок (я могу просто ограничитьпользователь в любом случае) для TabHost.Я не смог ничего сломать с помощью небольшого количества вкладок, чтобы помять, но я все еще беспокоюсь, что, возможно, я получаю доступ к базе данных плохим способом.

Как я могу предотвратить мои объекты SQLiteDatabase, чтобы вызватьблокировка?

Если я создам ContentProvider, исключит ли это возможность блокировки базы данных?

Есть ли у вас какие-либо предложения относительно изменений, которые я мог бы внести для доступа к данным из SQLiteDatabase?

В итоге я воспользовался классом Application и сохранил 1 SQLiteOpenHelper и изо всех сил старался его синхронизировать.Кажется, это работает отлично - я поместил все свои 25 действий в TabHost и помял их без ошибок.

Я вызываю метод ((SQLiteDbApplication)getApplication()).setDbHelper(new DBHelper(this, Constants.DB_NAME, null, Constants.DB_VERSION_CODE)); (показанный ниже) в каждом onCreate() вмои действия

Любые дальнейшие предложения по этому подходу или изменениям, которые я сделал, используя этот Application класс?

import android.app.Application;
import android.database.sqlite.SQLiteDatabase;

public class SQLiteDbApplication extends Application {
    private DBHelper dbHelper;
    private SQLiteDatabase db;
    public synchronized DBHelper getDbHelper() {
        db = dbHelper.getDatabase();//returns the already opened database object
        while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads());
        return dbHelper;
    }
    public synchronized void closeDb() {
        if(null != dbHelper)
            dbHelper.close();
        if(null != db)
            db.close();
    }

    @Override
    protected void finalize() throws Throwable {
        if(null != dbHelper)
            dbHelper.close();
        if(null != db)
            db.close();
        super.finalize();
    }
    public synchronized void setDbHelper(DBHelper dbHelper) {
        if(null == this.dbHelper) {
            this.dbHelper = dbHelper;
            this.dbHelper.setDb(this.dbHelper.getWritableDatabase());//creates and sets the database object via getWritableDatabase()
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 21 сентября 2010

Если вы беспокоитесь обо всех подключениях к базе данных, попробуйте ограничиться одним SqliteOpenHelper и обязательно оберните вокруг него слой синхронизации.

Вы можете расширить класс приложения , а затем вызвать getApplication и привести объект, который вы получите, в свое приложение. Теперь вы можете сохранить SqliteOpenHelper в этом классе приложения и создать свой собственный потокобезопасный метод доступа к соединению с базой данных.

Если вы используете AsyncTask во всех своих методах onCreate и у вас возникают проблемы с большим количеством вкладок, эти проблемы также могут возникать с более медленным устройством, более быстрым пользователем или базой данных, которая со временем увеличивается.

В зависимости от варианта использования вашего приложения вы можете пойти по пути сохранения и пройти через все усилия и трудности, связанные с многопоточностью и блокировкой, или вы можете просто опубликовать приложение с несколькими вкладками, которые никогда не вызывали ошибку, и убедитесь, что чтобы поймать исключение базы данных и отправить себе уведомление (например, с помощью Google Analytics), чтобы проверить, возникает ли проблема с многопоточностью в реальной жизни приложения.

2 голосов
/ 21 сентября 2010

Все обратные вызовы действий происходят в главном потоке, поэтому в описываемом вами сценарии многопоточность не выполняется, независимо от того, сколько у вас действий или вкладок.

ContentProvider не обеспечивает никакой блокировки,Фактически, он может ввести многопоточность там, где его еще нет, потому что он позволяет другим процессам выполнять вызовы в ваш собственный процесс, и когда это происходит, вызов отправляется из отдельного потока в вашем процессе (не в основной интерфейс пользователя).thread).

Конечно, если вы создаете свои собственные потоки, то у вас также будет многопоточность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...