11

バインドされたサービスがアプリでバックグラウンド作業を行うのに適しているかどうかを調べようとしています。要件は、さまざまなアプリケーション コンポーネントがさまざまな優先度の Web 要求を作成できることです。(したがって、サービスはある種のキューを維持し、優先度の高い他のリクエストに対する進行中のリクエストをキャンセルできる必要があります)。アプリケーションの使用が完了した後にサービスが実行されていることに気付かないように、サービスがユーザーにとって比較的目立たないようにしたいと思います-アプリケーションが閉じられている間も継続するより重要なことをしたい場合は、 startForeground( を使用できます) プロセス中に通知をプッシュします。

最初の解決策: アクティビティからのバインド

そのため、特定のアプリケーション コンポーネントについては、サービスにバインドして作業を完了できる必要があります。しかし、アクティビティがバインドを実行している場合、アクティビティが閉じられるため、構成の変更 (ローテーション) 中にバインドが失われるというよく知られた問題があるようです。

したがって、作成した別のコンテキスト ( new Context()) を使用して、それをサービスにバインドし、UI 以外のフラグメントを使用して、構成の変更が終了したと判断するまでこのコンテキストを維持できると考えていました。これは、構成の変更中にのみ、またはアクティビティからのバインディングの永続的な代替手段としてのみ行うことができました。(これは、構成の変更後もインスタンスを維持するための標準的で推奨される方法であることを指摘しておく必要があります)

ソリューション番号 2:

私が見る主な代替案は、アプリケーション コンテキストを使用してバインディングを行うことができるというものですが、これは長すぎる可能性がありますか? および/またはアプリのコンテキストとサービスの間に循環的な関係があり、サービスとアプリのコンテキストが破壊されるのを防ぐことができますか?

質問:

したがって、私が自分自身に答えようとしている質問は、最初の方法 (一時的なコンテキストを持つアクティビティ) を使用する必要があるかどうかです。それとも 2 番目 (サービスをアプリ コンテキストにバインドするだけ) ですか?

アプリのコンテキストがサービスに複数回バインドし、同じ回数だけバインドを解除できると考えるのは正しいですか? (つまり、コンテキストごとに複数の有効なバインディングを持つことができます)?

new Context()最初のソリューションで独自のコンテキスト ( ) を使用すると、問題が発生する可能性がありますか?

編集

詳細情報を見つけました: https://groups.google.com/forum/#!topic/android-developers/Nb58dOQ8Xfw

また、コンテキストを任意に「作成」することは難しいと思われるため、ソリューション 1 と 2 の組み合わせは、構成の変更全体でサービス接続が維持され、バインディングがアプリ コンテキストにある場合に適しているようです。アプリのコンテキストから 2 回バインドを解除する可能性については、まだ懸念があります。自分でバインディングの数を数えることは不要のようです-バインディングがコンテキストごとではなく接続ごとであることを確認/拒否できますか?

4

4 に答える 4

0

アクティビティで使用されるバインドされたサービスがある場合、同様の問題がありました。アクティビティ内で 、 を定義しServiceConnectionmConnection内部onServiceConnectedでクラス フィールドを設定しますsyncService。これはサービスへの参照です。

private SynchronizerService<Entity> syncService;

(...)

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        // We've bound to LocalService, cast the IBinder and get
        // LocalService instance
        Log.d(debugTag, "on Service Connected");
        LocalBinder binder = (LocalBinder) service;
        //HERE
        syncService = binder.getService();
        //HERE
        mBound = true;
        onPostConnect();
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        Log.d(debugTag, "on Service Disconnected");
        syncService = null;
        mBound = false;
    }
};

この方法を使用すると、方向が変わるたびに、サービスが実行されているにもかかわらず、変数をNullPointerException参照するときに が取得され、機能しないいくつかの方法を試しました。syncService

変数を保持するために保持されたフラグメントを使用して、Sam によって提案されたソリューションを実装しようとしていましたが、最初に簡単なことを試すことを思い出しましたsyncService。変数を静的に設定すると、向きが変わっても接続参照が維持されます!

だから今私は持っています

private static SynchronizerService<Entity> syncService = null;

...

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        // We've bound to LocalService, cast the IBinder and get
        // LocalService instance
        Log.d(debugTag, "on Service Connected");
        LocalBinder binder = (LocalBinder) service;
        //HERE
        if(syncService == null) {
            Log.d(debugTag, "Initializing service connection");
            syncService = binder.getService();
        }
        //HERE
        mBound = true;
        onPostConnect();
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        Log.d(debugTag, "on Service Disconnected");
        syncService = null;
        mBound = false;
    }
};
于 2014-07-07T14:07:58.017 に答える