ViewModel-Googleコンポーネント開発

3811 ワード

ViewModelクラスは、画面の回転などの構成変更においてデータが生き残るようにUIに関連するデータを格納および管理することを目的としています.また、Activity/fragmentとアプリケーションの残りの部分との通信(ビジネスロジッククラスの呼び出しなど)も処理します.
  永続化する理由は、OSがappリリースリソースを破棄した場合、ユーザーデータが失われないという2つの理由に基づいています.ネットワークが悪い場合やネットワークが切断された場合、appは動作を継続することができます.Modelはappデータ処理を担当するコンポーネントです.それらはViewまたはappコンポーネント(Activity,Fragmentなど)に依存しないため、それらのコンポーネントのライフサイクルの影響を受けません.UIコードのシンプルさを維持し、ビジネスロジックの分離により管理が容易になります.
ViewModelの目的はActivityまたはFragmentに必要な情報を取得して保存することです.ActivityやFragmentではViewModelの変化が観察できるはずです
ビューデータの所有権をUIコントローラから論理的に分離することは、より容易で効率的です.ライフサイクルには、UIコントローラ用のヘルプクラスであるView Modelという新しいクラスが用意されています.UIのデータを準備します.構成変更の間、ViewModelは自動的に保存され、保存されたデータがすぐに次のActivityまたはFragmentに使用できるようになります.
public class MyViewModel extends ViewModel {
    private MutableLiveData> users;
    public LiveData> getUsers() {
        if (users == null) {
            users = new MutableLiveData>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // do async operation to fetch users
    }
}

アクティビティがこのリストにアクセスできるようになりました.
public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

Activityが再作成されると、前のActivityによって作成された同じMyView Modelインスタンスが受信されます.所有者Activityが破棄されると、フレームワークはViewModelのonCleared()メソッドを呼び出し、リソースをクリーンアップできます.
ViewModelは、特定のActivityインスタンスおよびFragmentインスタンスを超えているため、Viewsまたはアクティブなコンテキストへの参照を持つ可能性のあるクラスを参照する必要はありません.View Modelがアプリケーションコンテキストを必要とする場合(たとえば、システム・サービスが見つかる場合)、Android View Modelクラスを継承し、コンストラクション関数でアプリケーションのコンストラクション関数を受信することができます.サブクラスには、アプリケーションを一意のパラメータとして受け入れるコンストラクション関数が必要です.(ApplicationクラスがContextを継承しているため).

Fragments間でデータを共有する


Activityの2つ以上のFragmentは、相互に通信する必要があります.したがって、この2つのFragmentは、いくつかのインタフェース記述を定義し、Activityは両方をバインドする必要があります.さらに、両方のFragmentは、他のFragmentがまだ作成されていないか非表示の場合を処理する必要があります.
この問題は、ViewModelオブジェクトを使用することで解決できます.主従Fragmentの一般的な状況を想像してみてください.ここにはFragmentがあり、ユーザーはリストから1つのプロジェクトを選択し、もう1つのFragmentは選択したプロジェクトの内容を表示します.
これらのFragmentは、Activityレンジを使用して、この通信を処理するために1つのViewModelを共有することができる.
各セグメントは、Activityで同じキーを使用してViewModelを取得できます.
public class SharedViewModel extends ViewModel {
    private final MutableLiveData selected = new MutableLiveData();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData getSelected() {
        return selected;
    }
}

public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onActivityCreated() {
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends LifecycleFragment {
    public void onActivityCreated() {
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // update UI
        });
    }
}

ただし、ViewModelProviderを取得する場合、両方のFragmentでgetActivity()が使用されます.これは、Activityの役割ドメインである同じSharedViewModelインスタンスが受信されることを意味します.
このアプローチのメリット:
  • Activityは、何もする必要はなく、この通信に関する内容も知らない.
  • SharedViewModelを除いて、Fragmentはお互いを理解する必要はありません.そのうちの1つが消えたら、もう1つは通常通りに仕事をします.
  • 各Fragmentには独自のライフサイクルがあり、他のFragmentのライフサイクルの影響を受けません.

  • ViewModelのライフサイクル


    ViewModelオブジェクトは、ViewModelを取得するときに、ViewModelProviderに渡すライフサイクルに限定されます.ViewModelはActivityが破棄またはFragmentが分離されるまでメモリに保持されます.