web-dev-qa-db-ja.com

ViewModelでのアクティビティライフサイクルへの反応

MVVMアーキテクチャを使用するアプリを作成しようとしていますが、理解できないことが1つあります。

公式Androidドキュメントは、ViewModelでアクティビティコンテキストを参照するのは良い考えではないと言っています(ViewModelがアクティビティを長引かせる可能性があるため)。アクティビティのときにアクションを実行したい場合、ユースケースについて疑問に思い始めました再開されます。

私はViewModelがビジネスロジックを実行すべきではないことを知っていますが、いくつかのサービスクラスを使用した場合(たとえば、一時停止時にアクティビティが再開および再開されるたびにGPSServiceが必要であるとします)、このサービス内でアクティビティonResumeに反応します(ライフサイクルオブザーバーを使用)監視されているアクティビティへの参照を保持する参照サービスを使用しているため、引き続きViewModelからこのアクティビティを参照します。これにより、アクティビティリークが発生する可能性があります(間違っている場合は修正してください)。

だから私の質問は、MVVMアーキテクチャでアクティビティまたはフラグメントライフサイクルにどのように反応するかです。

13
Androider

ViewModelがビジネスロジックを自分で実行すべきではないことを知っています

はい、あなたが正しい。 ViewModelにはビジネスロジックを含めないでください。ただし、UI関連のロジックを含める必要があります。つまり、基本的に、API呼び出しや場所に関連するものはViewModelロジックでは回避する必要があります。

では、アクティビティのライフサイクルに対応できるシナリオを作成したい場合はどうでしょうか。 LifecycleObserver を使用することをお勧めします。

Why?、LifecycleObserverLifecycleOwnerになるとコールバックが提供されるため、状態が変更されます。

ここに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)
}
}

LocationUpdatesContextに依存している場合は、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)
}
}

注意:まだカバーすることがたくさんありますが、この答えはできるだけ短くしてください。したがって、関連することについてまだ混乱している場合は、遠慮なくコメントで質問してください。回答を編集します。

7
Jeel Vankhede

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);
  }
}
0
farid_z