2011-08-11 12 views
1

私はいくつかのAPIを持つバインダを公開するLocalServiceを持っています。私はdataServiceListenerが公開中Binderが、私はdataServiceListeneronResult()方法で応答を取得するメソッドを呼び出した後アクティビティが閉じられて再開されたときのサービスコールバックを避ける

if (dataServiceListener == null) { 
    dataServiceListener = new DataServiceListener(); 
    mainActivity.getApplicationContext().bindService 
     (new Intent(mainActivity, LocalService.class), 
     dataServiceListener.svcConn, mainActivity.BIND_AUTO_CREATE); 
} 

:私はちょうどこのように、サービスリスナーを作成します。この時点までに、問題はなく、すべてが機能しています。 サービスリスナーのコールバックを待機しているアクティビティを閉じ直ちに再オープンすると、何らかの問題が発生します。 onCreate()dataServiceListenerを再インスタンス化しても、私は2つのコールバック、1つは破壊されたアクティビティの古いコールバック、もう1つは後ろのコールバックです。このように、結果はUI上で混在します。 サービスまたはサービスリスナーに、アクティビティが終了したときにコールバックを回避する必要があることを伝える方法はありますか。あるいは、ServiceListenerオブジェクトを破棄することさえできます。

私は、これはマーク・L.マーフィー(Commonsware)は「Androidの開発に忙しいコーダーズ・ガイド」で説明していることの問題だと思う:

最大の漁獲量は、活動が時にリスナーを後退させることを確認することですされております。

どうすればいいですか?アクティビティが終了したら不要なリスナーを取り除く方法はありますか?

ありがとうございました!

答えて

0

私はついにこの問題を解決しました(そして、私はそれほど長い間それを研究していませんでした:D)。

リスナーへのコールバックは、FragmentonDestroyが呼び出される前に行われました。したがって、ブール値 "dontupdate"の値は決してfalseに設定されませんでした。主なアクティビティのonBackPressedをオーバーライドすると、ブール値をfalseに設定する各フラグメントに対してdestroy()メソッドが呼び出されたので、問題を解決しました。

1

この問題もありました。終了すると、サービスからすべてのリソース、リスナー、スレッドを解放する必要があります。

+0

そして、どのように私はそれを達成することができますか?アクティビティが終了するとただちにリスナーを破棄する必要があります( 'onBackPressed()') – frapontillo

+0

あなたのアクティビティが終わったところでそれを行うことができます。また、完了したことを確認するには、 "onDestroy()"メソッドをオーバーライドすることもできますサービス.. –

+0

私はちょうどそれをしましたが、 'onDestroy'メソッドがonResultの直後に呼び出されるように見えるので、何も変わりません! – frapontillo

1

あなたのアクティビティは、リスナーとして登録/登録解除する必要があります。 onBackPressed()ではなく、適切なライフサイクルコールバックメソッドを使用する必要があります。登録onStart()、登録解除onStop()。これを行う1つの方法は、リスナーをサービスの静的メンバーにし、静的な登録/登録解除メソッドを提供することです。次に、あなたの活動から適切なものを呼び出します。

4

表示されているコードは、サービスにバインドするためのコードです。そのサービスにリスナーを登録している場所は表示されません。あなたはあなたの質問とonResult()メソッドへのあなたの参照に基づいて明らかにそうです。あなたの問題の性質を考えると、私は何をやっていることであることを推測するつもりです:onServiceConnected()onCreate()

  • にサービスへの結合

    1. 、あなたはBinder
    2. setListener()方法のいくつかの並べ替えを呼んでいますその場合

    、我々は構成の変更を無視した場合、問題をほどくための適切な方法は、onDestroy()で、その後、BinderにいくつかのremoveListener()メソッドを呼び出すunbindService()を呼び出すことであろう。

    設定変更は、特にプレフラグメントワールドでは、これを複雑にします。その理由は、this sample project(およびそれに付随する資料はthe bookです)がとても嫌な理由です。バインディングは厄介です。古いアクティビティからバインドを解除してサービスを継続しないと、新しいアクティビティがバインドされる前にサービスがシャットダウンされます。バインディングも状態です。あなたがリークすることがないように、単にバインドを解除できません。

    ので、レシピは次のようになります。

    1. バインドサービスにonCreate()で、onRetainNonConfigurationInstance()Binder
    2. setListener()メソッドの呼び出しのソートをonServiceConnected()ApplicationContext
    3. を使用して、をメモしますあなたは設定変更を受けており、Binder、あなたのListener、および残りのすべての州を含むObjectを返します。
    4. onCreate()
    5. getLastNonConfigurationInstance()を使用する - それはnullであれば、通常のように行いますが、それはnullない場合は、そのBinderListener上に保持し、onDestroy()では、再登録し、リスナー
    6. バインドを再していません上記のステップ3のフラグがfalse(つまり、であり、設定変更が行われていない)の場合は、BinderremoveListener()メソッドに電話し、次にunbindService()に電話してください。

    setRetainInstance(true)のフラグメントを使用すると、おそらくこれを簡略化できますが、私はまだそのサンプルを試していません。

  • +0

    私はそれだけでした。 基本的に、私は複数の断片で活動しています。同時に複数のタスクを実行する必要がある可能性があるため、各フラグメントには1つ以上のサービスバインディングを設定できます。 メインアクティビティの 'onBackPressed()'では、すべてのサービスリスナを 'boolean'値で動作しない状態に設定しました。それから私は活動を終える。しかし、これは期待どおりに機能しません。ブレークポイントを 'onBackPressed()'メソッドに設定しても問題ありませんが、何らかの理由でブレークポイントがなければ、onResult()メソッドは 'onBackPressed ) '! – frapontillo

    +0

    @MacGyver:「私はそれだけでした」 - あなたの説明は一致していないようです。たとえば、 'onBackPressed()'について言及していないことに気づくでしょう。 「各フラグメントは、同時に複数のタスクを処理する必要がある可能性があるため、1つ以上のサービスバインディングを持つことができます。 - それには複数のバインディングが必要ではありません。あなたは一つのサービスしか必要とせず、一つのバインダーしか必要としません。 – CommonsWare

    +0

    [OK]を、断片onDestroy()で私が今持っている:。 'dataServiceListener.serviceBinder.removeListener();' 'getActivity()getApplicationContext()unbindService(dataServiceListener.svcConn);' しかし、このdoesnの。何も変えない。 'removeListener()'は 'ServiceBinder'で' listener = null'を実行したばかりです。 – frapontillo

    8

    私は同じ問題がありました。私はAIDLを使用してリモートサービスで働いていました。私はこの問題を抱えていますが、foreachループ内のArrayList Collectionからremoveメソッドを使用してリスナーの登録を解除しようとしています。これは、比較でasBinderを使用していないためです。解決策を探して、私はRemoteCallbackListクラスをAndroid APIで見つけました。このクラスは、私が必要としていたことを正確に行い、簡単なやり方で、このタスクを含む苦労のためのすべての反応を取ったと思います。 、このクラスを使用するだけで、あなたのサービスと一緒に単一のインスタンスを作成し、クライアント・レジスタとしてのレジスタ(E)と登録解除(E)メソッドを呼び出して、あなたを登録解除する

    :AndroidのAPIから

    サービス。登録されたクライアントにコールバックするには、beginBroadcast()、getBroadcastItem(int)、およびfinishBroadcast()を使用します。

    ブロードキャストサンプル:

    int i = callbacks.beginBroadcast(); 
    while (i > 0) { 
        i--; 
        try { 
         callbacks.getBroadcastItem(i).somethingHappened(); 
        } catch (RemoteException e) { 
        // The RemoteCallbackList will take care of removing 
        // the dead object for us. 
        } 
    } 
    callbacks.finishBroadcast(); 
    
    関連する問題