新しい Androidが推奨するアーキテクチャ でAndroidサービスを配置する場所について考えるのに苦労しました。私は多くの可能な解決策を思いつきましたが、どれが最良のアプローチであるかについて決心することはできません。
私は多くの研究を行ったが、有用なガイドラインもチュートリアルも見つけられなかった。アプリアーキテクチャのどこにサービスを配置するかについて私が見つけた唯一のヒントは、@ JoseAlcerreca Medium post
理想的には、ViewModelsはAndroidについて何も知らないようにする必要があります。これにより、テスタビリティ、リークの安全性、モジュール性が向上します。一般的な経験則は、ViewModelsにAndroid。*のインポートがないことを確認することです(Android.Arch。*などの例外を除く)。同じことがプレゼンターにも当てはまります。
それによると、アクティビティコンポーネントと同じレベルで、Androidサービスをアーキテクチャコンポーネント階層の最上位に配置する必要があります。 AndroidサービスはAndroidフレームワークの一部であるため、ViewModelsはそれらについて知る必要がないためです。
ここで、シナリオを簡単に説明しますが、この特定のシナリオに対する答えが欲しいからではなく、パノラマを明確にするためだけです。
ここに私が考えることができる3つの異なるアーキテクチャがあります:
フラグメントとAndroidService間の共有ViewModel
BoundServicesはAndroid Frameworkの一部であり、Androidによって管理されるため、アーキテクチャの上に配置してアクティビティ/フラグメントのように扱う必要があると確信しています。 OSおよびそれらは、他のアクティビティおよびフラグメントにバインドされています。その場合、LiveData、ViewModels、Activities/Fragmentsを操作する最善の方法はわかりません。
データソースとして考えるべきだと思う人もいるかもしれませんが(私の場合はBluetoothを使用してスケールからデータを取得しているため)、前の段落で述べたことすべてのため、これは良い考えではないと思いますそして特に ここで言うことから :
アプリのエントリポイント(アクティビティ、サービス、ブロードキャストレシーバーなど)をデータのソースとして指定しないでください。代わりに、他のコンポーネントとのみ調整して、そのエントリポイントに関連するデータのサブセットを取得する必要があります。各アプリコンポーネントは、ユーザーのデバイスとのやり取りやシステムの全体的な現在の状態に応じて、寿命が短くなります。
だから、最後に、私の質問は次のとおりです。
Android(バウンド)サービスをどこに配置する必要があり、他のアーキテクチャコンポーネントとの関係は何ですか?これらの選択肢のいずれかが良いアプローチですか?
私の意見では、Serviceはと同じレベルにあるべきですActivity/Fragment、これはフレームワークコンポーネントであり、[〜#〜] mvvm [〜#〜ではないため]。ただし、そのため、サービスはLifecycleOwnerを実装せず、Android Framework Component、アプリケーションへのエントリポイントになる可能性があるため、データソースとして扱わないでください。
そのため、ここでのジレンマは、時々(あなたの場合)、Serviceはデータソースとして機能し、長時間実行されるタスクからUIにデータを提供します。
では、Android Architecture Componentに何があるべきでしょうか? LifecycleObserverとして扱うことができると思います。バックグラウンドで何をするにしても、LifecycleOwnerのライフサイクルについて考慮する必要があるためです。
どうして?なぜなら、通常はLifecycleOwner(Activity/Fragments)にバインドして長時間実行するタスクを行うためですUIから。したがって、LifecycleObserverのように扱うことができます。このようにして、サービスを「ライフサイクル対応コンポーネント」として作成しました!
どのように実装できますか?
service classを取り、それにLifecycleObserverインターフェースを実装します。
サービスを_Activity/Fragment
_にバインドする場合、サービスクラスのサービス接続中に、メソッドgetLifecycle().addObserver(service class obj)
を呼び出して、サービスをLifecycleObserverとしてアクティビティに追加します。
次に、サービスクラスのインターフェイスを使用して、サービスからUIにコールバックを提供し、データが変更されるたびに、サービスに少なくともLifecycleイベントがあるかどうかを確認します create または resume =コールバックを提供します。
このように、サービスからの更新にLiveData
を必要とせず、ViewModel
も必要ありません(なぜサービスに必要なのですか?サービスのライフサイクルで生き残るためには、構成の変更が必要です。そして、VMの主なタスクは、ライフサイクル間でデータを構成することです)。
私はあなたのためにそれを明確にしたことを願っています!
Androidサービスを使用しながら、サービスとの直接の接触を回避する1つの方法は、インターフェースオブジェクトを使用することです。これはインターフェース分離の「I」頭字語では、[〜#〜] solid [〜#〜]。小さな例を次に示します。
public interface MyFriendlyInterface {
public boolean cleanMethodToAchieveBusinessFunctionality();
public boolean anotherCleanMethod();
}
public class MyInterfaceObject implements MyFriendlyInterface {
public boolean cleanMethodToAchieveBusinessFunctionality() {
BluetoothObject obj = Android.Bluetooth.nastySubroutine();
Android.Bluetooth.nastySubroutineTwo(obj);
}
public boolean anotherCleanMethod() {
Android.Bluetooth.anotherMethodYourPresentersAndViewModelsShouldntSee();
}
}
public class MyViewModel {
private MyFriendlyInterface _myInterfaceObject;
public MyViewModel() {
_myInterfaceObject = new MyInterfaceObject();
_myInterfaceObject.cleanMethodToAchieveBusinessFunctionality();
}
}
上記のパラダイムを考えると、POJOコードを含むパッケージの外部にあるパッケージにサービスを自由に配置できます。サービスを配置するための「正しい」場所はありませんが、サービスを配置する場所は間違いなくあります(たとえば、POJOコードが行く場所)。