11

私のアプリは単一のActivity. このアクティビティでは、HandlerThreadソケット ブロック操作を行うためにループで実行される複数の を作成しています。

HandlerThread現在、私はこれらのすべての人に終了メッセージを投稿していActivity.onDestroy()ます.

アプリを開いて閉じて再起動すると、クラッシュすることがあります (多くの場合、実行されていないハンドラー スレッドにメッセージを投稿するためです)。

私の質問は次のとおりです。アプリを閉じるときの正しい終了方法は何ですか? HandlerThread(これらのスレッドがソケット操作をブロックしている可能性があることに注意してください)。

編集: 詳細: onCreate で開始されるハンドラー スレッドのプールがあります (初めてアプリを起動するときは問題ありません)。

各ハンドラの実行可能なループは、

 if (shouldRun) {
//body
} 
else { 
 close();
}

声明。

close メソッドは、保留中のすべてのメッセージとランナブルを削除し、メッセージをハンドラーに投稿して、ハンドラーにそのlooper.quit(). このように、現在のハンドラー スレッドが IO 操作によってブロックされている場合、一度だけ終了すると、彼は quit() を実行します。

4

5 に答える 5

3

はい、閉じたほうがいいです。また、コールバックを必ず削除してください。

@Override
public void onDestroy() {
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
    handler.getLooper().quit();
}
于 2013-02-18T08:46:39.123 に答える
1
    /**
 * Ask the currently running looper to quit.  If the thread has not
 * been started or has finished (that is if {@link #getLooper} returns
 * null), then false is returned.  Otherwise the looper is asked to
 * quit and true is returned.
 */
public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}

上記は HandlerThread.java のソース コードの 'quit' メソッドです。直接呼び出すだけです。

なぜ終了する必要がありますか?以下はHandlerThread.javaのソースコードのrunメソッドです。

    public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();//always loop except for a Message with null target

    mTid = -1;
}

答えは 'loop は 'while(true)' メソッドです。null ターゲットのメッセージを受信するまで戻ります。

于 2015-02-02T16:11:00.190 に答える
1
  • そこに矛盾がなければ、アプリはクラッシュしません。実行されていない HandlerThreadが本当に理由ですか? アクティビティを作成するときに HandlerThread オブジェクトを作成していませんか?
  • HandlerThreads が I/O 操作を待機している場合は、それらを中断することを検討します。単純にコールバックとメッセージを削除して Looper に終了を要求しても、終了メッセージを Handler に送信しても何も起こりません。HandlerThread オブジェクトは、Android がプロセスを強制終了する (発生する場合と発生しない場合があります) まで残ります。これは、おそらく到達できない「ゾンビ HandlerThread オブジェクトをアプリが収集する」ことを意味します。もちろん、これらの HandlerThreads に、それらがブロックしているチャネルに到着する終了メッセージを送信できる場合を除きます。
  • HandlerThread オブジェクトを再利用する方がずっと良いでしょう。サービスは、これを行うための適切なモデルである可能性があります。
  • また、スレッドがアクティビティを生き延びた場合は、スレッドの通信ピア (アクティビティ) がなくなったことをスレッドに通知する必要があります。そうしないと、すでになくなっているものを参照している可能性があります。
于 2013-02-18T09:01:25.763 に答える
0

ベスト プラクティス アプローチは、アクティビティ内のハンドラーへのコールバックを削除することonDestroy()です。詳細については、この回答を参照してください。

https://stackoverflow.com/a/5038542/1369222

于 2013-02-18T08:50:42.480 に答える
0

Looper が終了すると、HandlerThread は停止します。アクティビティを停止すると、 HandlerThread.getLooper().quit() 。( http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app/IntentService.java#IntentService.ServiceHandler.%3Cinit%を参照してください。適切な HandlerThread の使用例については、3E%28android.os.Looper%29を参照してください)

于 2013-02-18T09:01:24.010 に答える