音楽プレーヤーアプリを開発しています。私は複数のフラグメントを持つメインアクティビティを持っており、それぞれがデバイスアルバム、アーティストなどで曲を表示しています。
私はすべての再生およびその他のものを処理する音楽サービスを持っています。
混乱しているのは、このサービスとさまざまなフラグメントのバインディングです。
今、私はメインアクティビティと各フラグメントを個別にサービスとバインドしており、かなりうまく機能しています。しかし、これが本当にベストプラクティスかどうか疑問に思いました。メインアクティビティをサービスにバインドし、それを子フラグメントで使用する方法はありますか?
アクティビティやフラグメント、サービスの非常に基本的な概念が欠けている可能性があります。だから誰かがこの点で私を導いてください。
これは概念的な質問のほうが多いので、コードは必要ありません。それでも必要な場合はお知らせください。
編集:
私の質問は次のとおりです。複数の子フラグメント(それぞれがサービスを使用する)を持つアクティビティとサービスをバインドするより良い方法は何ですか?
Service
ではなくFragment
をアクティビティにバインドします。アプリケーションの説明(複数のFragment
が入れ替えられた1つのアクティビティ)は、これを最も(そして本当に唯一の)実用的なアプローチにします。
Service
をActivity
にバインドすると、そのライフサイクルはActivity
のライフサイクルに結び付けられます。 「Bound Services 」を参照してください。アクティビティでFragment
を追加または削除するたびに、Fragment
が作成および破棄されます。新しいフラグメントが作成または破棄されるたびにサービスを作成および破棄する必要があるため、このプロセスにサービスをリンクしようとするのは望ましくありません。
代わりに、ホストActivity
にバインドします。次に、バインドされたサービスにアクセスするためのインターフェースを使用して、またはIntent
によって、フラグメントからのホストアクティビティと対話できます。
よりクリーンなアーキテクチャは、フラグメントから直接バインドすることだと思います。 Rarwの回答で概説されている問題に関しては、アクティビティとフラグメントからサービスにバインドすることもできます。このようにして、アクティビティが破棄されなくなるまでサービスが存在することを確認します。
フラグメントから接続することには、2つの主な利点があります。
サービス接続は非同期であるため、フラグメント内では、アクティビティから取得しているサービスがnullでないことを実際に確信することはできません。これにより、少なくともいくつかのnullポインターチェックと、フラグメントが作成されたときとサービスが接続されたときの両方でフラグメントを更新するメカニズムにつながります(そのため、どちらが先に発生してもデータを表示することが確実です)。
フラグメントが存在する特定のアクティビティには依存しません。アクティビティからサービスを取得するには、アクティビティ固有のクラスへのキャストを行っていると思います。サービスを取得するためにBoundActivity
のようなメソッドを使用してgetBoundService
のようなインターフェイスを作成することもできますが、ポイント1の利点を考慮するとオーバーヘッドになると思います。複数のサービスがある場合はどうでしょうか。
[〜#〜]更新[〜#〜]
これは、これを示す非常に単純なプロジェクトです。 https://github.com/ena1106/FragmentBoundServiceExample
信頼できることがわかった唯一の方法は、[Fragment
でローダーを使用することです。
Loader
を作成しますcontext
のLoader
を使用(フラグメントのactivity
が呼び出されたときにinitLoader
でonCreate
に設定)forceLoad()
を呼び出すonStartLoading
を使用して、ServiceConnection
でサービスをバインドしますonStartLoading
/onStopLoading
にコールバックを登録しますonStopLoading
のサービスをアンバインドしますこのライブラリ、イベントバスパブリッシュ/サブスクライブパターンでイベントバスパターンを使用してトレイを作成できます。 https://github.com/greenrobot/EventBus 詳細については、プロジェクトサイトを確認してください。
イベントをサービスとの間で、アクティブまたはフラグメントに送信できます
フラグメントのライフサイクルの初めにサービスからフラグメントにデータを取得する必要がある場合、主にデバイスをローテーションするときに、onServiceConnected onアクティビティをまだ呼び出すことができず、NPEを取得します。サービスはbindService()ではなくstartService()で開始されるため、フラグメントに独自の接続を確立させるのは良い考えだと思います。
getActivity()
を使用すると、フラグメントからアクティビティにアクセスできます
私のホストアクティビティでサービスをバインドし、引数で設定されたバンドルによってIbinderのオブジェクトを渡します。
そして私のコードはこれを好きかもしれません:
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//put service in bundle
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};