0

私はおしゃべりネット対応アプリケーションを作成しており、ユーザーエクスペリエンスを向上させるために、あらゆる種類の同時実行構造を使用しています。ネットワークから入ってくる情報には、テキスト項目と画像の URL が含まれています。現在、画像をフェッチするために新しいスレッドを生成せずに、ブロッキング方式で画像をフェッチしています。これは問題なく機能しますが、別のスレッドを生成して画像をフェッチすることで、物事をよりスムーズにできることに気付きました。このタスクを処理するために 2 つのワーカー スレッドを持つスレッド プールに落ち着きましたが、アプリがクラッシュするという断続的な問題が発生しています。ランダムに発生するようで、正確に何が問題なのかわかりません。だからここに私が現在やっている方法があります:

  1. ユーザーが検索をタップすると、必要な情報を取得するために新しい AsyncTask が生成されます。

  2. 新しい AsyncTask では、情報が少しずつ入ってきます。1 つの項目について十分な情報が得られるとすぐに、その項目をリスト アダプターに追加し、メイン スレッドにジャンプしてnotifyDataSetChanged()、リストを更新するために呼び出します。また、タスクをスレッド プールに送信してイメージをフェッチし、イメージnotifyDataSetChanged()の準備ができたらすぐに呼び出します。

  3. 処理するアイテムがなくなるまで、リストの更新を続けます。

私の設定はかなり良いと思いますが、やり方を改善するための提案と、クラッシュの原因を追跡するための指針が欲しいです。

logcat の出力は次のとおりです。

02-23 21:30:20.303: DEBUG/AndroidRuntime(1209): VM をシャットダウンしています 02-23 21:30:20.313: WARN/dalvikvm(1209): threadid=1: キャッチされない例外で終了するスレッド (group=0x4001d800) 02 -23 21:30:20.342: ERROR/AndroidRuntime(1209): FATAL EXCEPTION: main 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): java.lang.IllegalStateException: アダプターの内容が変わったが ListView通知を受け取りませんでした。アダプターのコンテンツがバックグラウンド スレッドからではなく、UI スレッドからのみ変更されていることを確認してください。[ListView(16908298、class android.widget.ListView) with Adapter(class android.widget.HeaderViewListAdapter)] 02-23 21:30:20.342: ERROR/AndroidRuntime(1209): at android.widget.ListView.layoutChildren(ListView) .java:1492) 02-23 21:30:20.342: エラー/AndroidRuntime(1209): android.widget.AbsListView.onLayout(AbsListView.

4

1 に答える 1

3

アイテムが利用可能になると、AsyncTaskのワーカースレッドからリストアダプターを更新しているようです。同じアダプターがUIスレッドでトラバースされ、リストがレンダリングされます。これにより、前のアイテムに応答している間に次のアイテムのリストアダプターを更新している可能性があるため、ランダムにクラッシュする可能性がありますnotifyDataSetChanged()

リストアダプターを更新するより良い方法は、ハンドラーを使用してランナブルをUIスレッドに投稿し、リストアダプターを更新してを呼び出すことnotifyDataSetChanged()です。

画像の更新でも同様のことが起こっている可能性があります。

一般的な戦略として、UIが依存するデータ構造はUIスレッドで更新する必要があります。それは至る所でより安全である傾向があります。別の戦略は、コードのクリティカルセクションを注意深く同期することですが、それを正しく行うのははるかに困難です。

于 2011-02-24T05:33:03.900 に答える