Данные, введенные в sqlite, автоматически удаляются при перезапуске приложения в Android Pie

Данные SQLite исчезли после перезапуска приложения в android pie. Приложение работает нормально в других версиях, но в android pie, когда вы перезапускаете приложение, несколько последних записей не видны. база данных не полностью пуста, как показывают другие записи.

Я попытался установить режим WAL в false, отключив WriteAheadLogging, который, кажется, работает на некоторых устройствах, но проблема не была полностью решена, поскольку некоторые устройства все еще сообщали о проблемах, поэтому я попытался установить режим журнала PRAGMA на TRUNCATE, но это также не сработало.

 public myDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
 @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.disableWriteAheadLogging();

      Cursor c1=db.rawQuery("PRAGMA journal_mode=TRUNCATE",null);
      c1.close();
    }


    public static synchronized myDbHelper getInstance(Context context) {


        if (mInstance == null) {
            mInstance = new myDbHelper(context.getApplicationContext());
         mInstance.setWriteAheadLoggingEnabled(false);
        }
        return mInstance;
    }

Затем в моем фрагменте: myDbHelper dbHelper = myDbHelper.getInstance(getActivity());

Я не получаю никаких сообщений об ошибках, просто несколько последних записей не отображаются, как будто они не были сохранены в базе данных. Любая помощь приветствуется.

вы слышали о библиотеке Room?. Абстрактный слой над SQL

Lakhwinder Singh 05.07.2019 12:46

Да, но мое приложение создано с использованием преобразователя содержимого. Мне нужно преобразовать его в комнату, что может занять некоторое время, и мне нужно предоставить исправление сейчас.

ANKIT 05.07.2019 12:49

Опубликуйте код, в котором вы инициализируете БД

Lakhwinder Singh 05.07.2019 12:50

public myDbHelper (контекст контекста) { super (контекст, DATABASE_NAME, null, DATABASE_VERSION); } Затем в моем фрагменте myDbHelper dbHelper = myDbHelper.getInstance(getActivity());

ANKIT 05.07.2019 12:54

обновление в вопросе

Lakhwinder Singh 05.07.2019 12:58

Вопрос был обновлен

ANKIT 05.07.2019 13:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
1 202
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не думаю, что проблема напрямую связана с включенным или выключенным режимом WAL, а скорее с тем, что вы, возможно, неправильно определяете последние несколько записей.

Кодирование mInstance.setWriteAheadLoggingEnabled(false); напрямую отключит WAL до того, как будет вызван сам onConfigure (см. ниже)

Первое, что я бы сделал, это изменил

public myDbHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

к :-

private myDbHelper(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

Чтобы вы случайно не получили экземпляр румянаmyDBHelper.

Вы также можете, в качестве временной меры, добавить следующий метод в свой класс myDBHeleper:

public void logMode(SQLiteDatabase db, String tagextra, String dbname, Context context) {
    Log.d("BUILD","Build is " + Build.VERSION.SDK_INT);
    File dbf = new File(context.getDatabasePath(dbname).toString());
    File dbfwal = new File(dbf.getPath() + "-wal");
    File dbfshm = new File(dbf.getPath() + "-shm");
    if (dbfwal.exists()) {
        Log.d("-WALCHK " + tagextra,"The -wal file was found an is " + String.valueOf(dbfwal.length()));
    } else {
        Log.d("-WALCHK " + tagextra,"The -wal file doesn't exist.");
    }
    if (dbfshm.exists()) {
        Log.d("-SHMCHK " + tagextra,"The -shm file was found an is " + String.valueOf(dbfwal.length()));
    } else {
        Log.d("-SHMCHK " + tagextra,"The -shm file doesn't exist");
    }
    if (db == null) {
        db = this.getWritableDatabase();
    }
    Cursor csr = db.rawQuery("PRAGMA journal_mode",null);
    if (csr.moveToFirst()) {
        Log.d("LOGMODE " + tagextra ,"Database mode is " + csr.getString(0));
    }
}

Затем это можно использовать, чтобы выяснить, существует ли режим, а также существуют ли файлы -wal и -shm и есть ли какие-либо данные.

Короче говоря, его можно использовать для устранения любых опасений, что проблема связана с режимом WAL.

Например, используя следующее приближение вашего класса myDatabaseHelper. Однако в дополнение к вашему коду: -

  • вызов вышеупомянутого метода логмоде был включен в соответствующие моменты.
  • onCreateMethod был включен для создания таблицы и добавления начальной строки.
  • конструктор был сделан частный

Так это выглядит :-

public class myDbHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "mydb";
    public static final int DATABASE_VERSION = 1;

    public static final String TBL_USER = "user";
    public static final String COL_USER_ID = BaseColumns._ID;
    public static final String COl_USER_NAME = "_name";
    public static final String COL_USER_EMAIL = "_email";
    public static final String COl_USER_PASSWORD = "_password";

    private static myDbHelper mInstance;
    private Context mContext;

    private myDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mContext = context;
        logMode(this.getWritableDatabase(),"CONSTRUCT",DATABASE_NAME,context); // Note will force an open
    }
    @Override
    public void onConfigure(SQLiteDatabase db) {
        logMode(db, "ONCONFIG1", DATABASE_NAME,mContext);
        super.onConfigure(db);
        db.disableWriteAheadLogging();
        logMode(db,"ONCONFIG2",DATABASE_NAME,mContext);
        Cursor c1=db.rawQuery("PRAGMA journal_mode=TRUNCATE",null);
        c1.close();
        logMode(db,"ONCONFIG3",DATABASE_NAME,mContext);
    }


    public static synchronized myDbHelper getInstance(Context context) {

        if (mInstance == null) {
            mInstance = new myDbHelper(context.getApplicationContext());
            mInstance.setWriteAheadLoggingEnabled(false);
        }
        mInstance.logMode(mInstance.getWritableDatabase(),"INSTANCE",mInstance.getDatabaseName(),context );
        return mInstance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        logMode(db,"ONCREATE1",DATABASE_NAME,mContext);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TBL_USER +
                "(" +
                COL_USER_ID + " INTEGER PRIMARY KEY," +
                COl_USER_NAME + " TEXT UNIQUE," +
                COL_USER_EMAIL + " TEXT," +
                COl_USER_PASSWORD + " TEXT" +
                ")");
        //Add a row when oncreate is called
        db.execSQL("INSERT INTO " + TBL_USER + " (" +
                COl_USER_NAME + "," +
                COL_USER_EMAIL + "," +
                COl_USER_PASSWORD +
                ") VALUES('testuser','[email protected]','1234567890')");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long addUser(String name, String email, String passowrd) {
        ContentValues cv = new ContentValues();
        cv.put(COl_USER_NAME,name);
        cv.put(COL_USER_EMAIL,email);
        cv.put(COl_USER_PASSWORD,passowrd);
        SQLiteDatabase db = this.getWritableDatabase();
        logMode(db,"ADDUSER1",DATABASE_NAME,mContext);
        return db.insert(TBL_USER,null,cv);
    }

    public void logMode(SQLiteDatabase db, String tagextra, String dbname, Context context) {
        Log.d("BUILD","Build is " + Build.VERSION.SDK_INT);
        File dbf = new File(context.getDatabasePath(dbname).toString());
        File dbfwal = new File(dbf.getPath() + "-wal");
        File dbfshm = new File(dbf.getPath() + "-shm");
        if (dbfwal.exists()) {
            Log.d("-WALCHK " + tagextra,"The -wal file was found an is " + String.valueOf(dbfwal.length()));
        } else {
            Log.d("-WALCHK " + tagextra,"The -wal file doesn't exist.");
        }
        if (dbfshm.exists()) {
            Log.d("-SHMCHK " + tagextra,"The -shm file was found an is " + String.valueOf(dbfwal.length()));
        } else {
            Log.d("-SHMCHK " + tagextra,"The -shm file doesn't exist");
        }
        if (db == null) {
            db = this.getWritableDatabase();
        }
        Cursor csr = db.rawQuery("PRAGMA journal_mode",null);
        if (csr.moveToFirst()) {
            Log.d("LOGMODE " + tagextra ,"Database mode is " + csr.getString(0));
        }
    }
}

Следующее находится в методе onStart фрагмента: -

@Override
public void onStart() {
    super.onStart();
    myDbHelper dbHelper = myDbHelper.getInstance(getActivity());
    dbHelper.logMode(dbHelper.getWritableDatabase(),"FRGONSTRT1",myDbHelper.DATABASE_NAME,getActivity());
    dbHelper.addUser("Fred","[email protected]","password");
    Cursor csr = dbHelper.getReadableDatabase().query(myDbHelper.TBL_USER,null,null,null,null,null,null);
    DatabaseUtils.dumpCursor(csr);
    csr.close();
}

Вот оно:-

  1. получает экземпляр myDBHelper.
  2. вызывает метод logMode.
  3. добавляет строку.
  4. извлекает все данные в Cursor и выгружает Cursor.

Тестирование

Тест 1

Удаление приложения на Android (эмулятор) с API 28 и запуск приводит к: -

2019-07-07 10:38:56.022 D/BUILD: Build is 28
2019-07-07 10:38:56.022 D/-WALCHK ONCONFIG1: The -wal file was found an is 16512
2019-07-07 10:38:56.022 D/-SHMCHK ONCONFIG1: The -shm file was found an is 16512
2019-07-07 10:38:56.023 D/LOGMODE ONCONFIG1: Database mode is wal
2019-07-07 10:38:56.038 D/BUILD: Build is 28
2019-07-07 10:38:56.038 D/-WALCHK ONCONFIG2: The -wal file doesn't exist.
2019-07-07 10:38:56.038 D/-SHMCHK ONCONFIG2: The -shm file doesn't exist
2019-07-07 10:38:56.039 D/LOGMODE ONCONFIG2: Database mode is truncate
2019-07-07 10:38:56.039 D/BUILD: Build is 28
2019-07-07 10:38:56.039 D/-WALCHK ONCONFIG3: The -wal file doesn't exist.
2019-07-07 10:38:56.039 D/-SHMCHK ONCONFIG3: The -shm file doesn't exist
2019-07-07 10:38:56.040 D/LOGMODE ONCONFIG3: Database mode is truncate
2019-07-07 10:38:56.041 D/BUILD: Build is 28
2019-07-07 10:38:56.042 D/-WALCHK ONCREATE1: The -wal file doesn't exist.
2019-07-07 10:38:56.043 D/-SHMCHK ONCREATE1: The -shm file doesn't exist
2019-07-07 10:38:56.043 D/LOGMODE ONCREATE1: Database mode is truncate
2019-07-07 10:38:56.054 D/BUILD: Build is 28
2019-07-07 10:38:56.054 D/-WALCHK CONSTRUCT: The -wal file doesn't exist.
2019-07-07 10:38:56.055 D/-SHMCHK CONSTRUCT: The -shm file doesn't exist
2019-07-07 10:38:56.055 D/LOGMODE CONSTRUCT: Database mode is truncate
2019-07-07 10:38:56.056 D/BUILD: Build is 28
2019-07-07 10:38:56.057 D/-WALCHK INSTANCE: The -wal file doesn't exist.
2019-07-07 10:38:56.057 D/-SHMCHK INSTANCE: The -shm file doesn't exist
2019-07-07 10:38:56.058 D/LOGMODE INSTANCE: Database mode is truncate
2019-07-07 10:38:56.058 D/BUILD: Build is 28
2019-07-07 10:38:56.058 D/-WALCHK FRGONSTRT1: The -wal file doesn't exist.
2019-07-07 10:38:56.058 D/-SHMCHK FRGONSTRT1: The -shm file doesn't exist
2019-07-07 10:38:56.059 D/LOGMODE FRGONSTRT1: Database mode is truncate
2019-07-07 10:38:56.059 D/BUILD: Build is 28
2019-07-07 10:38:56.059 D/-WALCHK ADDUSER1: The -wal file doesn't exist.
2019-07-07 10:38:56.059 D/-SHMCHK ADDUSER1: The -shm file doesn't exist
2019-07-07 10:38:56.060 D/LOGMODE ADDUSER1: Database mode is truncate
2019-07-07 10:38:56.069 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@4f533b6
2019-07-07 10:38:56.070 I/System.out: 0 {
2019-07-07 10:38:56.070 I/System.out:    _id=1
2019-07-07 10:38:56.070 I/System.out:    _name=testuser
2019-07-07 10:38:56.070 I/System.out:    [email protected]
2019-07-07 10:38:56.070 I/System.out:    _password=1234567890
2019-07-07 10:38:56.070 I/System.out: }
2019-07-07 10:38:56.070 I/System.out: 1 {
2019-07-07 10:38:56.070 I/System.out:    _id=2
2019-07-07 10:38:56.070 I/System.out:    _name=Fred
2019-07-07 10:38:56.070 I/System.out:    [email protected]
2019-07-07 10:38:56.070 I/System.out:    _password=password
2019-07-07 10:38:56.070 I/System.out: }
2019-07-07 10:38:56.070 I/System.out: <<<<<

В этом случае из-за строки

logMode(this.getWritableDatabase(),"CONSTRUCT",DATABASE_NAME,context); // Note will force an open 

вызывается перед

mInstance.setWriteAheadLoggingEnabled(false);

База данных изначально находится в режиме WAL, но строка db.disableWriteAheadLogging(); в методе onConfigure изменяет режим на усечение и при этом фиксирует транзакции (в файле -вал есть невыполненные транзакции, так как его размер больше 0, (-shm в основном является копия файла -wal)) согласно :-

2019-07-07 10:38:56.022 D/-WALCHK ONCONFIG1: The -wal file was found an is 16512

Транзакции были зафиксированы, так как во всех последующих выводах файл -вал был удален.

Тест 2

Приложение перезапускается (т.е. теперь с существующими данными), вывод: -

2019-07-07 10:52:11.722 I/InstantRun: starting instant run server: is main process
2019-07-07 10:52:11.812 D/BUILD: Build is 28
2019-07-07 10:52:11.812 D/-WALCHK ONCONFIG1: The -wal file was found an is 0
2019-07-07 10:52:11.812 D/-SHMCHK ONCONFIG1: The -shm file was found an is 0
2019-07-07 10:52:11.813 D/LOGMODE ONCONFIG1: Database mode is wal
........... subsequent output the same as first bar times

Хотя база данных изначально находится в WAL, незавершенных транзакций нет (единственное отличие).

Тест 3

Если строка logMode(this.getWritableDatabase(),"CONSTRUCT",DATABASE_NAME,context); // Note will force an open закомментирована, а приложение удалено и перезапущено: -

2019-07-07 10:56:23.314 I/InstantRun: starting instant run server: is main process
2019-07-07 10:56:23.437 D/BUILD: Build is 28
2019-07-07 10:56:23.438 D/-WALCHK ONCONFIG1: The -wal file doesn't exist.
2019-07-07 10:56:23.438 D/-SHMCHK ONCONFIG1: The -shm file doesn't exist
2019-07-07 10:56:23.439 D/LOGMODE ONCONFIG1: Database mode is truncate
........... subsequent output the same as first bar times

Затем первое использование (поскольку открытие не принудительно до db.disableWriteAheadLogging(); вызова) приводит к тому, что база данных находится в режиме TRUNCATE.

Изменение с общедоступного на частный в классе myDbHelper вызывает следующую ошибку в классе провайдера: myDbHelper(Context) имеет частный доступ в myDbHelper private myDbHelper mDbHelper; @Override public boolean onCreate() { mDbHelper = new myDbHelper(getContext()); вернуть ложь; }

ANKIT 07.07.2019 08:21

@ANKIT, тогда проблема может быть в этом, а не в режиме WAL/Journal. Вы должны использовать получить экземпляр для получения экземпляра mDbHelper. Поэтому я сказал экземпляр румяна. Что довольно ясно, так это то, что причина не в данном коде.

MikeT 07.07.2019 08:26

Изменение публичного логического значения onCreate() { mDbHelper = new myDbHelper(getContext()); вернуть ложь; } в общедоступное логическое значение onCreate() { mDbHelper = myDbHelper.getInstance(getContext()); вернуть ложь; } устранена ошибка частного доступа в классе провайдера. Но была ли решена реальная проблема с отсутствием некоторых данных, еще предстоит проверить, поскольку это происходит иногда, а не каждый раз при перезапуске приложения, поэтому это трудно проверить, и это влияет только устройства с Android Pie.

ANKIT 07.07.2019 09:04

Другие вопросы по теме