5

別のプロセスで実行されているサービスがあります。メインプロセスのUIスレッドがonDestroy()を終了した後、アプリケーションコンテキストにバインディングを提供し、BIND_AUTO_CREATEを指定したにもかかわらず、サービスが破棄されていることがわかりました。

私のメインプロセスのUIスレッドonCreate()には、次のバインディングコードがあります。

Intent intent = new Intent(mAppContext, MyService.class);
mAppContext.bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);

私のメインプロセスのUIスレッドonDestroy()には、次のバインド解除コードがあります。

mAppContext.unbindService(mMyServiceConnection);

stopService()を呼び出さないことに注意してください。

bindService()に関するAndroidのドキュメントには次のように書かれています。

サービスは、呼び出しコンテキストが存在する限り、システムによって必要と見なされます。

私がそれを正しく読んでいる場合、私はアプリケーションのコンテキストを提供したので、サービスはアプリケーションの存続期間中システムによって必要とされていると見なされます。

アプリケーションのコンテキストはonDestroy()で死ぬのではないかと思いました。これは、AndroidのドキュメントがgetApplicationContext()について述べていることです。

現在のプロセスの単一のグローバルApplicationオブジェクトのコンテキストを返します。

アプリケーションのコンテキストがonDestroy()で停止する場合、Androidには大きな問題があると思います。問題は、ディスプレイが回転すると、onDestroy()が呼び出されることです(直後にonCreate()が続きます)。したがって、その効果は、ディスプレイが回転したときに発生します-私の場合、それは非常に頻繁に発生します!-私のサービスは常に終了します。

私のアプリのプロセスのpidは決して変更されないことに注意してください。つまり、同じプロセスです。これは、「現在のプロセス」と記載されているgetApplicationContext()のドキュメントに照らして重要です。

これが私のデバッグログが示すものです:

04-03 05:15:12.874:DEBUG / MyApp(841):main onDestroy
04-03 05:15:12.895:DEBUG / MyApp(847):service onUnbind
04-03 05:15:12.895:DEBUG / MyApp(847 ):service onDestroy
04-03 05:15:12.934:DEBUG / MyApp(841):main onCreate
04-03 05:15:12.966:DEBUG / MyApp(847):service onCreate
04-03 05:15:12.975:DEBUG / MyApp(847):サービスonBind

だから私の質問は:

1)バインド/バインド解除についての私の理解は正しいですか?

2)UIスレッドのonDestroy()が呼び出されたときに、サービスが破棄されないようにする方法はありますか?

質問2のハックは、バインドを解除しないことです。しかし、onDestroy()が呼び出されるたびにバインディングがリークしているので、私はそれが好きではありません。リークされたバインディングが1つあることを「覚えて」、それだけをリークすることはできましたが、カスケードされたハックがあり、それは本当に醜いです。

4

3 に答える 3

4

1) はい、あなたの理解は正しいと思います (私が思うと言ったのは、あなたの言っていることを理解していると思うからです ;-) )。使用しているフラグは、「誰かがバインドしようとするとこのサービスを自動的に開始し、誰かがバインドされている限り実行し続けますが、誰もバインドされていない場合は、気軽に終了してください」という意味です。

2)ここでSTART_STICKY説明されているように、フラグを確認します。これにより、呼び出し元に何が起こっても、サービスを開始して実行し続けることができます。Context

一般に、onDestroy()あなたのアクティビティが殺されようとしていることを意味します。ディスプレイを回転させると、Activityが強制終了され、再作成されます。Bundle適切な方法で状態を に保存し、 で復元する責任がありonCreate()ます。

于 2011-04-03T06:14:45.553 に答える
0

あなたのサービスは殺されますか:

  1. Activityスタックに秒がある場合は?
  2. 構成の変更を処理する場合は?

アプリケーションが破棄された後もサービスを維持する必要があるのはなぜですか?

一般的な経験則では、アクティビティやサービスがいつ停止するかはわかりません。これが達成しようとしている何かを妨げている場合は、それを回避する賢い方法があるかもしれません.

編集- 方向設定の変更を実際に処理して、アクティビティが再開されないようにすることができます。詳細については、この回答の後半を参照してください。

「2番目」について:活動を開始してから活動をActivity開始するイメージ。が表示されている間に画面を回転させると、再起動します。この時点で再開されますか?よくわかりませんが、方向の変更中もアプリケーションを存続させ、アプリケーションを存続させる傾向があるという予感があります。これは、サービスを維持するための別の戦略である可能性があります。ABBBAA

于 2011-04-03T06:33:03.433 に答える
0

サービスは、次の両方が true の場合にのみ破棄されます。

  1. bindService() へのすべての呼び出しは、対応する unbindService() への呼び出しと一致しています。
  2. 誰かが startService() を呼び出した場合、誰かが stopService() も呼び出したか、サービスが stopSelf() を呼び出しました。

サービスは、開始することも、接続をバインドすることもできます。このような場合、サービスが開始されているか、Context.BIND_AUTO_CREATE フラグを使用してサービスへの接続が 1 つ以上ある限り、システムはサービスを実行し続けます。これらの状況がいずれも成立しない場合、サービスの onDestroy() メソッドが呼び出され、サービスは事実上終了します。

これにより、かなり正確で安全な優れたソリューションが得られます。

bindService と startService の両方の場合、サービスを必要とする 2 つのアクティビティ (この例では「ビューアー」と「チャット」) があるとします。また、バインダーを使用して、onStart と onStop の間に「viewer_connected」と「chat_connected」を更新します。

次に、サービスはこれを行うスレッドでループを実行します。

public isRunning = true;
while (isRunning) {

    if (viewer_connected) {
        // send update to viewer activity
    }

    if (chat_connected) {
        // send update to chat activity
    }

    try {
        Thread.sleep(5000);
    } catch (Exception e) { isRunning=false; }

    // 3 second timeout before destroying service
    if (!viewer_connected && !chat_connected) {
        try { Thread.sleep(3000); } catch (Exception e) { isRunning=false; }

        if (!viewer_connected && !chat_connected) isRunning=false;
    }

}
stopSelf();

これが機能するのは、サービスを破棄する前に、アンバインドするアクティビティとサービスを stopself() する必要があるためです。つまり、サービスが破棄される前にタイムアウトが発生します。

于 2016-03-17T15:28:33.860 に答える