6

私はやや複雑な問題を抱えており、ここの誰かが私を助けてくれることを願っています.

クリック イベントで、スレッドを作成し、このメソッドに基づいて実行時間の長い操作を開始します。長時間実行タスクが完了すると、別のメソッドへのコールバックが実行され、ハンドラーへのポストが実行されます。

@Override
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) {
    remindersList = newRemindersList;
    mHandler.post(mUpdateDisplayRunnable);
}

Runnable を呼び出すもの:

// post this to the Handler when the background thread completes
private final Runnable mUpdateDisplayRunnable = new Runnable() {
  public void run() {
    updateDisplay();
  }
};

最後に、私の updateDisplay() メソッドが行っていることは次のとおりです。

private void updateDisplay() {
    if (csModel.getState() != Model_ContentSearch.State.RUNNING) {
        if(remindersList != null && remindersList.size() > 0){
                r_adapter = new ReminderAdapater(Activity_ContentSearch.this, remindersList, thisListView);
                thisListView.setAdapter(r_adapter);
                r_adapter.notifyDataSetChanged();
        }
    }
}

これを通常に行うと、これは美しく機能します。ただし、長時間実行されている操作の実行中に向きを変更すると、機能しません。コールバックを適切に作成し、remindersList にはアイテムが含まれています。しかし、この行に到達すると:

r_adapter.notifyDataSetChanged();

何も起こりません。奇妙なことに、別の送信を行い、プロセス全体を (向きを変更せずに) 再度実行すると、実際にはビューが 2 回更新されます。したがって、ビューは最初の送信の結果で 1 回更新され、2 番目の送信の結果で 1 秒後に更新されます。したがって、アダプター DID はデータを取得しますが、ビューを更新していません。

これがオリエンテーションの変更と関係があることは知っていますが、私の人生では理由を理解できません. 誰でも助けることができますか?または、向きを変更してスレッドを処理する別の方法を誰かが提案できますか?

バラ

4

2 に答える 2

6

問題は、方向を変更すると、新しいアクティビティが最初からスピンアップされることです (onCreate)。長時間実行されているプロセスには、古い (表示されなくなった) アクティビティへのハンドルがあります。古いアクティビティを適切に更新していますが、画面に表示されていないため表示されません。

これは簡単に修正できる問題ではありません。ただし、役立つライブラリがあります。それはDroidFuと呼ばれています。これは、あなたが見ているものの根本的な原因と、DroidFu ライブラリがそれとどのように戦うかを (私よりもはるかに正確に) 説明しているブログ投稿です: http://brainflush.wordpress.com/2009/11/16/introducing-droid- fu-for-android-betteractivity-betterservice-and-betterasynctask/

編集:(アクティブなアクティビティを追跡するためのコードを追加)

アプリケーション クラスにこれを追加します。

private Activity _activeActivity;
public void setActiveActivity(Activity activity) {
    _activeActivity = activity;
}
public Activity getActiveActivity() {
    return _activeActivity;
}

アクティビティに、これを追加します。

@Override
public void onResume() {
    super.onResume();
    ((MyApplicationClassName)getApplication()).setActiveActivity(this);
}

MyApplicationClassName.getActiveActivity(); を呼び出して、アクティブなアクティビティを取得できるようになりました。

これは DroidFu のやり方ではありません。DroidFu は onCreate でアクティブなアクティビティを設定しますが、それほど堅牢ではないと思います。

于 2010-06-21T05:43:00.840 に答える
1

私は同様の問題を抱えていました.ListAdapterでnotifyDataSetChangedを呼び出す時間のかかるスレッドsendEmptyMessageをハンドラーに持っていました。向きを変えるまではうまくいきました。

UI スレッドで 2 番目のハンドラーを宣言し、最初のハンドラーをこのハンドラーに sendEmptyMessage にすることで解決しました。これにより、ListAdapter で notifyDataSetChanged が呼び出されます。そして、ListAdapter を static として宣言します。

私は初心者なので、それが醜い解決策であるかどうかはわかりませんが、私にとってはうまくいきました...

Jere.Jones の説明から、これは次のように機能すると仮定します。古いアクティビティのハンドルに EmptyMessage を送信し、新しいアクティビティのハンドルに EmptyMessage を送信します。

于 2011-03-06T18:00:05.720 に答える