LiveDataの特性とデータ損失の問題または異常問題の解析

5254 ワード

LiveData

  • きほんとくせい

    1.メモリ漏洩なし:Observerは独自のLifecycleオブジェクトにバインドされているため、Lifecycleが破棄されると自動的にクリーンアップされます.2.Activityの停止によってクラッシュすることはありません.ObserverのLifecycleがアイドル状態(たとえば、activityがバックグラウンドにある場合)の場合、変更イベントは受信されません.3.常に最新のデータを保持:Lifecycleが再起動した場合(たとえば、activityがバックグラウンドから起動状態に戻った場合)、最新のロケーションデータが受信されます(新しいデータが更新されたり、再購読されたりします).4.構成変更を正しく処理する:activityまたはfragmentが構成変更(デバイス回転など)によって再作成された場合、最新の有効位置データがすぐに受信されます.5.リソース共有:MyLocationListenerインスタンスを1つだけ保持し、システムサービスに1回だけ接続し、アプリケーション内のすべてのオブザーバーを正しくサポートできます.6.ライフサイクルを手動で管理しないで、fragmentは必要なときにデータを観察するだけで、停止される心配がないか、停止した後に観察を開始する必要がないことに気づいたかもしれません.fragmentはデータを観察するときにLifecycleを提供するため、LiveDataは自動的に管理します.
  • 基本的な使い方


  • /**
  • ViewModel **/public class SampleViewModel extends ViewModel { private MutableLiveData sampleLiveData; public MutableLiveData getSampleLiveData() { if (sampleLiveData == null) { sampleLiveData = new MutableLiveData(); } return sampleLiveData; }
  • // 
    sampleLiveData.setValue(data);
    
    // 
    sampleLiveData.postValue(data);
    

    }/**
  • Activity/public class SampleActivity extends AppCompatActivity { private SampleViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); viewModel = ViewModelProviders.of(this).get(SampleViewModel.class); final Observer observer = new Observer() { @Override public void onChanged(@Nullable final String dataStr) { textView.setText(dataStr); } }; viewModel.getSampleLiveData().observe(this, observer); } }/
  • Fragment **/public class SampleFragment extends Fragment { private SampleViewModel viewModel; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); viewModel = ViewModelProviders.of(this).get(SampleViewModel.class); final Observer observer = new Observer() { @Override public void onChanged(@Nullable final String dataStr) { textView.setText(dataStr); } }; viewModel.getSampleLiveData().observe(this, observer); } } Note:LiveDataがViewModelで更新されていることを確認します.理由は次のとおりです.
  • ActivityとFragmentの肥大化を避ける.このようにUIは、リレーショナル・データの取得やステータスを必要とせずに、表示するデータに関心を持つ必要があるだけです.LiveDataをViewModelに引き抜くことで、ActivityとFragmentの再構築後にデータが失われないようにします.
    observeForever
    viewModel.getSampleLiveData().observeForever(observer); viewModel.getSampleLiveData().removeObserver(observer);
    カスタムLiveData
    public class CustomLiveData extends LiveData{/**通知可能なobserver/@Override protected void onActive(){super.onActive()}/*通知できるobserver*/@Override protected void onInactive(){super.onInactive();}
    MediatorLiveData
    private MutableLiveData data1 = new MutableLiveData<>();
    private MutableLiveData data2 = new MutableLiveData<>();
    private MediatorLiveData mediatorLiveData = new MediatorLiveData<>();
    private void sample(@NonNull LifecycleOwner owner) {
        mediatorLiveData.addSource(data1, new Observer() {
            @Override
            public void onChanged(@Nullable String s) {
                mediatorLiveData.setValue(s);
            }
        });
        mediatorLiveData.addSource(data2, new Observer() {
            @Override
            public void onChanged(@Nullable String s) {
                mediatorLiveData.setValue(s);
            }
        });
        
        mediatorLiveData.observe(owner, new Observer() {
            @Override
            public void onChanged(@Nullable String s) {
            }
        });
        // mediatorLiveData.removeSource();
    }
    

    更新データロスの問題について
    UIが表示するときliveDataを呼び出す.postValue("a"); liveData.setValue("b"); 先に「b」を受け取ってから「a」を受け取る
    UIが非表示の場合、liveDataを呼び出す.postValue("a"); liveData.setValue("b"); UIが表示されると、setValueが先に実行され、postValueによって更新されるため、「a」しか受信されません.
    UIが表示するときliveDataを呼び出す.setValue("a"); liveData.setValue("b"); liveData.setValue("c"); liveData.setValue("d"); liveData.setValue("e"); 「a」「b」「c」「d」「e」の順に受け取ります
    UIが表示するときliveDataを呼び出す.postValue("a"); liveData.postValue("b"); liveData.postValue("c"); liveData.postValue("d"); liveData.postValue("e"); 「e」しかもらえません
    UIが表示するときliveDataを呼び出す.postValue("a"); liveData.postValue("b"); liveData.postValue("c"); liveData.postValue("d"); liveData.setValue("e"); 「e」を先に受け取り、「d」を受け取る
    UIが非表示の場合、liveDataを呼び出す.setValue("a"); liveData.setValue("b"); liveData.setValue("c"); liveData.setValue("d"); liveData.setValue("e"); UIが表示されると、「e」のみが受信されます.
    UIが非表示の場合、liveDataを呼び出す.postValue("a"); liveData.postValue("b"); liveData.postValue("c"); liveData.postValue("d"); liveData.postValue("e"); UIが表示されると、「e」のみが受信されます.
    UIが非表示の場合、liveDataを呼び出す.setValue("a"); liveData.setValue("b"); liveData.setValue("c"); liveData.setValue("d"); liveData.postValue("e"); UIが表示されると、「e」のみが受信されます.
    UIが非表示の場合、liveDataを呼び出す.postValue("a"); liveData.postValue("b"); liveData.postValue("c"); liveData.postValue("d"); liveData.setValue("e"); UIが表示されると、「d」のみが受信されます.