2

Webサービスとのイベント同期を使用してアプリでカスタムカレンダーを作成しようとしています。

すべてがうまくいきます(まあ、実際にはそうではありません)。

カレンダーアクティビティは、AsyncTask当月のイベントを取得してデータベースに保存するために開始され、onPostExecuteメソッドはビューを更新して毎日適切にマークを付けます。

私の問題は、ユーザーがカレンダーアクティビティに到達し、すぐにメインアクティビティに数回戻るときに発生します。たとえば、

Main Activity> Calendar Activity(戻るボタンを押す)>> Main ActivityCalendar Activity戻るボタンを押す)>..。

この時点で、アクティビティがフリーズするdatabase lock has not been available for 30 sec.か、アプリがクラッシュします。SQLiteConstraintException: error code 19

編集SQLiteConstraintException動作はもう起こりません

私のアプリでは更新が非常に重要であるため、カレンダーアクティビティを再入力するたびに、データベースを削除し、サーバーの新しいデータを再入力します。これは同じですが、この時点でロックが行われます。

編集

Delete > Insertスタイルを次 のように変更しました:Updateすべてのデータ(flag列を設定= 0)>Insert新しいデータ(flag列を設定= 1)> Deleteflag列= 0を設定)

私はすでにこのソリューションを試しましたがAsyncTask、アクティビティの終了をキャンセルして成功しませんでした

問題は、自分がしていることのプロセスを完全に理解していないことだと確信しているので、本当に重要な(または基本的な)何かが欠けています。

私のコードを改善したり、正しい方向に向けたりする手助けをいただければ幸いです。

前もって感謝します!

編集

私のアプリケーションにはAplication、単一のデータベース接続(getWriteableDatabase();)の作成を担当するがあり、この独自の接続は到達可能なトラフMyApp.getDatabase();メソッドです。

4

2 に答える 2

1

DBへのアクセスをシリアル化してみてください。SQLiteDatabaseの各インスタンスは、SQLiteDBへの個別のリンクを表します。単一のSQLiteDatabaseインスタンスで実行されるアクションはシリアル化されますが、複数のスレッドで複数のSQLiteDatabaseインスタンスをいじると、説明したようなバグが発生し始めます。

コードを投稿しなかったので、AsyncTasksのデータベースにアクセスするたびに新しいSQLiteDatabaseインスタンス(.getWriteableDatabase()/ .getReadableDatabase()を使用)を取得すると想定しています。単一のSQLiteDatabaseインスタンスを使用して、それをタスクに渡してみてください。このようにして、dbアクセスをシリアル化し、AsyncTaskスレッドがDBロックを奪い合うのを防ぎます。

于 2012-11-19T18:14:15.937 に答える
0

メインアクティビティ>カレンダーアクティビティ(戻るボタンを押す)>メインアクティビティ>カレンダーアクティビティ(戻るボタンを押す)>..。

AsyncTaskこれにより、カレンダーを開くたびに新しいものが作成され、開始される可能性があります。

AsyncTaskすぐにキャンセルしない場合でも、それぞれが実行されます。

AsyncTaskまた、並列実行するかシリアル化するかは、実行に使用するAndroidのバージョン/エグゼキューターによって異なります。> = Honeycombのデフォルトの動作は、シリアル実行です。ドキュメントの実行順序のセクションで説明されています。AsyncTask

シリアルAsyncTaskを使用する場合、いくつかの(古い)タスクをキューに入れることができ、最新のタスクが実行されるまでにかなりの時間がかかる場合があります。アクティビティを終了するときにタスクをキャンセルすることをお勧めします。

表示されるdatabase lock has not been available for 30 sec.警告は、あるスレッドに書き込み、同時に別のスレッドからデータベースにアクセスしようとしていることを示しています。それが並列に2つの書き込みスレッドを必要とするかどうかはわかりません。

問題は、異なるSQLiteDatabaseインスタンスを使用していないことです。Androidは、ランダムなSQLiteDatabaseオブジェクトがデータベースに書き込みロックを持っているかどうかを確認できないため、警告の代わりにエラーが発生すると思います。

では、何ができるでしょうか。トランザクションなしでデータベースを長時間ロックすることはほとんど不可能なので、トランザクションを使用すると思います。

  • トランザクションのサイズを特定の量に制限して、他のスレッドからデータベースを使用するための間に中断が保証されるようにします。
  • を使用してトランザクションを動的に停止しdb.yieldIfContendedSafely()ます。これにより、別のスレッドがデータベースにアクセスするかどうかがチェックされ、トランザクションが一時的に終了します。欠点:変更がコミットされ、トランザクション全体をロールバックすることはできません。
  • ログ先行書き込みのドキュメントに記載されているように、SQLiteDatabase#enableWriteAheadLogging()&を試してみてください。beginTransactionNonExclusive()ロックの問題なしにマルチスレッドアクセスを許可できるように読めます。それが機能するかどうか、そしてそれがどのような副作用を持っているかについては、これ以上調査していません。
于 2012-11-20T16:24:01.580 に答える