MVVMアーキテクチャを使用するアプリを作成しようとしていますが、理解できないことが1つあります。
公式Androidドキュメントは、ViewModelでアクティビティコンテキストを参照するのは良い考えではないと言っています(ViewModelがアクティビティを長引かせる可能性があるため)。アクティビティのときにアクションを実行したい場合、ユースケースについて疑問に思い始めました再開されます。
私はViewModelがビジネスロジックを実行すべきではないことを知っていますが、いくつかのサービスクラスを使用した場合(たとえば、一時停止時にアクティビティが再開および再開されるたびにGPSServiceが必要であるとします)、このサービス内でアクティビティonResumeに反応します(ライフサイクルオブザーバーを使用)監視されているアクティビティへの参照を保持する参照サービスを使用しているため、引き続きViewModelからこのアクティビティを参照します。これにより、アクティビティリークが発生する可能性があります(間違っている場合は修正してください)。
だから私の質問は、MVVMアーキテクチャでアクティビティまたはフラグメントライフサイクルにどのように反応するかです。
ViewModelがビジネスロジックを自分で実行すべきではないことを知っています
はい、あなたが正しい。
ViewModel
にはビジネスロジックを含めないでください。ただし、UI関連のロジックを含める必要があります。つまり、基本的に、API呼び出しや場所に関連するものはViewModel
ロジックでは回避する必要があります。
では、アクティビティのライフサイクルに対応できるシナリオを作成したい場合はどうでしょうか。 LifecycleObserver
を使用することをお勧めします。
Why?、LifecycleObserver
がLifecycleOwner
になるとコールバックが提供されるため、状態が変更されます。
ここにLifecycleOwner
とは?私たちの場合、それはActivity/Fragmentかもしれません。
では、どのようにしてこれを達成できますか?
アクティビティの再開および一時停止期間中にmake locationリクエストを実行するとします。
そのため、以下のようにLocationUpdates
というクラスをLifecycleObserver
として作成できます。
class LocationUpdates : LifecycleObserver {
constructor(){
// some basic location related initialization here
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectListener() {
// this method will respond to resume event of our Lifecycle owner (activity/fragment in our case)
// So let's get location here and provide callback
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectListener() {
// this method will respond to pause event of our Lifecycle owner (activity/fragment in our case)
// So let's stop receiveing location updates here and remove callback
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) // Optional if you want to cleanup references
fun cleanUp() {
// this method will respond to destroy event of our Lifecycle owner (activity/fragment in our case)
// Clean up code here
}
}
これで、アクティビティから直接LocationUpdates
を作成し、コールバックを受け取ることができます。
class MyActivity : AppCompatActivity() {
private lateinit var mLocationUpdates: LocationUpdates
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Initialize your LifecycleObserver here & assign it to this activity's lifecycle
lifecycle.addObserver(mLocationUpdates)
}
}
ライフサイクルの処理方法 & Codelabsの例を参照できます。
そのジョブにViewModel
が必要な場合は、次のことを考慮してください。
class MyViewModel : ViewModel {
private lateinit var mLocationUpdates: LocationUpdates
constructor() : super() {
// initialize LocationUpdates here
}
// Assign our LifecyclerObserver to LifecycleOwner
fun addLocationUpdates(lifecycle: Lifecycle){
lifecycle.addObserver(mLocationUpdates)
}
//Optional, we really don't need this.
fun removeLocationUpdates(lifecycle: Lifecycle){
lifecycle.removeObserver(mLocationUpdates)
}
}
LocationUpdates
がContext
に依存している場合は、AndroidViewModel
の使用を検討してください。
これで、LiveData
を使用して任意のアクティビティ/フラグメントで場所の更新を観察し、LifecycleObserver
を以下のように割り当てることができます。
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by lazy {
return@lazy ViewModelProviders.of(this@MyActivity).get(MyViewModel::class.Java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.addLocationUpdates(lifecycle)
}
}
注意:まだカバーすることがたくさんありますが、この答えはできるだけ短くしてください。したがって、関連することについてまだ混乱している場合は、遠慮なくコメントで質問してください。回答を編集します。
ViewModelをライフサイクル対応にする必要がある場合は、ViewModelにLifeCycleObserverを実装させ、必要に応じてライフサイクルイベントをオーバーライドできます。例、
public class MyModel extends ViewModel implements
LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
protected void onLifeCycleStop() {
// do something
}
}
次に、アクティビティまたはフラグメントで、ビューモデルをアクティビティライフサイクルの所有者に追加できます。
public class MyActivity extends AppCompatActivity {
protected MyModel mMyModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMyModel = ViewModelProviders
.of(this)
.get(MyModel.class);
getLifecycle().addObserver(mMyModel);
}
}