1

奇妙なバグがあります。バッテリーがなくなると、アプリはデータ(SQLiteに保存されている)を失いますが、アプリケーションを強制的に強制終了してからバッテリーがなくなると、失われません。

何が原因かわかりません。

編集1:

データを失うとはどういう意味ですか?

  1. ユーザーが登録すると、ユーザー名などが保存されます。
  2. アプリが閉じられ、強制的に閉じられ、ユーザーがアプリを再度開くと、ユーザー名が表示されます
  3. バッテリーがなくなり、アプリがフォアグラウンドで実行されている場合。バッテリーが再充電され、ユーザーがアプリを再度開くと、ユーザー名はなくなります。

オブジェクトはどのように保存されますか:


 public Void perform(SQLiteDatabase db) {
                final ConfigEntry entry = new ConfigEntry(property, value);

                if(contains(property)) {
                    db.update(ConfigEntry.TABLE_NAME, databaseAdapter.convertToContentValues(entry), ConfigEntry.COLUMN_NAME + " = ?", new String[] { property });
                } else {
                    db.insertOrThrow(ConfigEntry.TABLE_NAME, null, databaseAdapter.convertToContentValues(entry));
                }
                return null;
            }
        });

したがって、基本的にdb.insertOrThrowが呼び出されます。

データベースを初期化する方法は次のとおりです。


public  S doInTransaction(TransactionTask task) {
        DatabaseHelper mDbHelper = DatabaseHelper.getInstance(mContext);
        SQLiteDatabase mDb = mDbHelper.getWritableDatabase();
        mDb.setLockingEnabled(true);
        mDb.beginTransaction();
        try {
            S result = task.perform(mDb);
            mDb.setTransactionSuccessful();
            return result;
        } finally {
            mDb.endTransaction();
        }
    }

4

3 に答える 3

1

問題は、を使用していることですbeginTransaction()。電話をかける場合は、次の電話 beginTransaction()をかける必要があります。

db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }

以下またはあなたのデータは保存されません。理由はここsqliteマニュアル

にありますそしてあなたのデータが保存されない理由はあなたがトランザクションを開始し db.setTransactionSuccessful();、システムがそれを閉じようとしたために呼び出されなかった場合、データは保存されないからです。ただしfinally{}、まだ呼び出される可能性がありますが、呼び出されなかったという事実は変わりませんdb.setTransactionSuccessful();

于 2013-01-16T22:43:16.893 に答える
1

よくわかりませんが、さらに深く掘り下げるための質問やインスピレーションを提供できることを願っています。

  1. データベースが完全な初期作成プロセスを通過するかどうか、またはテーブルはあるがユーザー名のみが欠落しているかどうかを監視しましたか?デバイスからデータベースファイルをダウンロードして、PCのSQLiteツールでコンテンツを確認できますか?

  2. 内部でデータベースを開きますdoInTransaction()が、そこでは閉じません。

    public S doInTransaction(TransactionTask task) {
        DatabaseHelper mDbHelper = DatabaseHelper.getInstance(mContext);
        SQLiteDatabase mDb = mDbHelper.getWritableDatabase();
        //mDb.setLockingEnabled(true); // true is default, so it can be removed
        mDb.beginTransaction();
        S result = null;
        try {
            result = task.perform(mDb);
            mDb.setTransactionSuccessful();
        } finally {
            // rolls back if setTransactionSuccessful() wasn't called
            mDb.endTransaction();
            mDb.close();
        }
        return result;
    }
    
  3. 同じデータベースを使用していることを完全に確信していますか?誰かがデータベース名の一部としてタイムスタンプを使用したことを一度見たので、私は尋ねます。

  4. 誤ってインメモリデータベースを作成していませんか?

  5. デバイスがローバッテリーで死ぬには、複数の異なる方法があります。デバイスが完全に停止するか、実際に緊急シャットダウンを行うことができます。どちらが当てはまりますか?アプリがオフになったときにアプリが行うことの内部を提供する可能性のあるロギングはありますか?

要約すると、理由はあなたが提供したコードにあるとは思えません。あなたが言ったように、コードはボタンが押されたときにのみ実行されます。それはさらなる調査のために上記の質問を残します(もちろん、私が見逃したかもしれないいくつかがあります...)。

于 2013-01-16T23:24:11.190 に答える
0

すべてのヘルプに感謝し、私たちはついに答えを見つけました。

ユーザーパスワードを使用してデータベースを暗号化し、デバイスのMACアドレスを使用してパスワードをソルトします。

何が起こったのかというと、起動後にユーザーがバッテリーを使い果たしたとき、アプリを実行してMACアドレスを要求したときに、ネットワークカードがまだ無効になっているなどの理由で失敗することがありました。その場合、DBを読み取ろうとすると失敗する新しいソルトを作成しました。

于 2013-01-17T16:01:02.293 に答える