0

アクティビティから、ListViewのDataAdapterのコンテンツを更新するために、45秒ごとにAsyncTaskを起動するハンドラーを作成しています。AsyncTaskはうまく機能し、ProgressUpdatesとToastメッセージを通じて進行状況をユーザーに通知し続けます。

スレッドのdoInBackgroundはファイアアンドフォーゲットであり、再利用できないため、45秒ごとに起動するAsyncTaskの新しいインスタンスをHanderから作成する必要があります。問題は、Handerが再作成され、AsyncTaskの新しいインスタンスが作成されたために画面が回転し、同時にメッセージが消えてしまうことです。そのため、ProgressUpdatesとToastメッセージの使いやすいユーザーの進行は圧倒的であり、ListViewの利用が困難になります。

そして、これを解決策として提案しないでください。android:screenOrientation="portrait"はオプションではありません。

頻繁に実行する必要があるものについては、AsyncTaskクラスではなく、カスタムThreadを使用する必要がありますか?ToDo:表示されていません。後で、センサーのonSensorChangedイベントからアダプターを更新して、ListView内の各場所の方位を更新する必要があります。毎回ユーザーに通知する必要がないため、個別のAsyncTaskクラスで実行します。デバイスのベアリングが変更されました。

AsyncThreadは再利用できないので、これはすべて間違っていますか?つまり、アクティビティでListViewを更新し、UIスレッドをオフにしておくための最良の方法は何ですか?

4

2 に答える 2

1

問題は、画面が回転し、Handerが再作成されてAsyncTaskの新しいインスタンスが作成されたために、同時メッセージが消える場合です。

APIアクティビティから引用する理由-構成の変更

特に指定しない限り、構成の変更(画面の向き、言語、入力デバイスなどの変更など)により、現在のアクティビティが破棄され、onPause()、onStop()、およびの通常のアクティビティライフサイクルプロセスが実行されます。必要に応じてonDestroy()。

したがって、すべてのオブジェクトにはアクティビティスコープのライフサイクル(つまり、アクティビティクラス内で定義されたHandler、AsyncTaskなど)があり、このアクティビティのレクリエーションの影響を受けます。ただし、アクティビティ-構成の変更セクションの後の段落で説明されているように、このアクティビティのレクリエーションをバイパスすることができます。

特殊なケースでは、1つ以上のタイプの構成変更に基づいて、アクティビティの再開をバイパスしたい場合があります。これは、マニフェストのandroid:configChanges属性を使用して行われます。そこで処理すると言うあらゆるタイプの構成変更について、再起動する代わりに、現在のアクティビティのonConfigurationChanged(Configuration)メソッドへの呼び出しを受け取ります。ただし、構成の変更に処理しないものが含まれる場合でも、アクティビティは再開され、onConfigurationChanged(Configuration)は呼び出されません。

トピックとは関係ありませんが、良い習慣として、アクティビティが終了しようとしているとき(つまり、onDestroy()メソッド内)に、使用済みオブジェクト(Handler、AsyncTaskなど)を常に適切に破棄する必要があります。

頻繁に実行する必要があるものについては、AsyncTaskクラスではなく、カスタムThreadを使用する必要がありますか?

AsyncTaskは非常に便利ですが、定期的なタスクには適していません。この場合は、ScheduledExecutorServiceまたはTimerTaskを使用します。サンプルコードについては、こちらの回答を確認してください。

于 2012-05-05T09:54:26.753 に答える
0

コードを少し投稿していただけますか?問題がどこにあるかを理解することが役立つ場合があります。

yorkが指摘しているように、おそらくを使用する必要がありますTimerTask。それはあなたがやろうとしていることによく合っているようです。

問題を引き起こすのがハンドラーの新しいインスタンスの作成である場合は、次のようなことを試すことができます。

private Handler mHandler = null;

@Override
public void onCreate(Bundle _savedInstanceState) {
    super.onCreate(_savedInstanceState);
    setContentView(R.layout.my_layout);

    if (mHandler == null) {
        // TODO create your handler here
    }
}

編集: _savedInstanceState==nullもテストできます。
_savedInstanceStateはアクティビティの状態を保存するために使用されるため、電話を回しても問題はなくなります。ただし、アクティビティを終了してからそのアクティビティに戻ると、新しいハンドラーが作成されます(静的変数としてインスタンス化する場合を除く)。

于 2012-05-05T19:37:50.497 に答える