是否可以在Android SQLite数据库上禁用WAL?

时间:2012-08-10 12:14:03

标签: android sqlite

在这几个启用了WAL(提前写入日志记录)的Android设备上,我确实遇到了很多数据库备份/恢复问题。在创建这样的数据库之后是否可以关闭它?

我的想法是:

1。)一个包装器,可以在较旧的Android设备上运行:

public class SQLiteDatabaseWalWrapper {

    private boolean        available;
    private Method         disableWriteAheadLogging;
    private Method         enableWriteAheadLogging;
    private Method         isWriteAheadLoggingEnabled;
    private SQLiteDatabase sqliteDatabase;

    public SQLiteDatabaseWalWrapper(final SQLiteDatabase sqliteDatabase) {
        this.sqliteDatabase = sqliteDatabase;

        available = false;

        try {
            disableWriteAheadLogging = SQLiteDatabase.class.getMethod("disableWriteAheadLogging");
            enableWriteAheadLogging = SQLiteDatabase.class.getMethod("enableWriteAheadLogging");
            isWriteAheadLoggingEnabled = SQLiteDatabase.class.getMethod("isWriteAheadLoggingEnabled");

            available = true;
        } catch (NoSuchMethodException noSuchMethodException) {
        }
    }

    public boolean checkAvailable() {
        return available;
    }

    public void disableWriteAheadLogging() {
        if (disableWriteAheadLogging != null) {
            try {
                disableWriteAheadLogging.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }
    }

    public boolean enableWriteAheadLogging() {
        boolean result = false;

        if (enableWriteAheadLogging != null) {
            try {
                result = (Boolean) enableWriteAheadLogging.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }

        return result;
    }

    public boolean isWriteAheadLoggingEnabled() {
        boolean result = false;

        if (isWriteAheadLoggingEnabled != null) {
            try {
                result = (Boolean) isWriteAheadLoggingEnabled.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }

        return result;
    }
}

2。)在使用AsyncTask的扩展应用程序中,我将发出一个完整的检查点并关闭WAL:

public class MyApplication extends Application {

    private class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(final Void... voids) {
            // Make a full checkpoint
            sqliteDatabase.execSQL("PRAGMA wal_checkpoint(FULL);");

            // switch WAL off
            sqliteDatabaseWalWrapper.disableWriteAheadLogging();
        }

        @Override
        protected void onPostExecute(final Boolean result) {
        }
    }

    private Context                  context;
    private SQLiteDatabase           sqliteDatabase;
    private SQLiteDatabaseWalWrapper sqliteDatabaseWalWrapper;
    private MySQLiteOpenHelper       sqliteOpenHelper;
    private MyAsyncTask              task;

    @Override
    public void onCreate() {
        super.onCreate();

        context = getApplicationContext();

        sqliteOpenHelper = new MySQLiteOpenHelper(context);
        if (sqliteOpenHelper != null) {
            sqliteDatabase = sqliteOpenHelper.getWritableDatabase();
            if (sqliteDatabase != null) {

                if (Build.VERSION.SDK_INT >= 16) {
                    sqliteDatabaseWalWrapper = new SQLiteDatabaseWalWrapper(sqliteDatabase);
                    if (sqliteDatabaseWalWrapper != null && sqliteDatabaseWalWrapper.checkAvailable() && sqliteDatabaseWalWrapper.isWriteAheadLoggingEnabled()) {
                        task = new MyAsyncTask();
                        task.execute();
                    }
                }
            }
        }
    }

    @Override
    public void onTerminate() {
        if (sqliteDatabase != null) {
            sqliteDatabase.close();
        }

        if (sqliteOpenHelper != null) {
            sqliteOpenHelper.close();
        }

        super.onTerminate();
    }
}

这会有用吗?这会删除SQLite在启用WAL的数据库上创建的各种附加文件吗?这会导致回到Android文档中描述的单个数据库文件吗?

3 个答案:

答案 0 :(得分:1)

在数据库上执行PRAGMA journal_mode=DELETE应删除Wal模式并返回正常的操作方法。

此处提供完整文档:http://www.sqlite.org/wal.html

答案 1 :(得分:0)

以编程方式我们可以启用和禁用WAL模式。它自API级别11以来一直存在

请参阅此文档以获取更多信息

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()

答案 2 :(得分:0)

setJournalMode(RoomDatabase.JournalMode.TRUNCATE)