平凡エンジニアからの出発

一に努力、二に理想、三に積小為大。

【AndroidTraining】ViewModel 1

Lesson

ViewModel 1

Mission

下記の仕様を満たすアプリを作りましょう。

  • ViewModelを使い、カウントアップさせる

Snap Shot

◆テスト

  • 画面を回転しても、カウントアップが継続すること
  • 画面がバックグラウンドへ移動しても、カウントアップが継続すること
f:id:atuyan39:20210420231021p:plain:w300f:id:atuyan39:20210420231027p:plain:w300

Step by Step

1 . テンプレートから、New > Activity > Fragment + ViewModelを選択して、TrainingViewModelActivityを新規に追加する
f:id:atuyan39:20210420231033p:plain:w600

2 . FragmentのレイアウトファイルにTextView, Buttonを追加する
3 . ◆ViewModelの実装を行う
4 . LiveDataを定義する

private MutableLiveData<String> mText;

5 . ViewからLiveDataを取得できるようにメソッド追加

@NonNull
public MutableLiveData<String> getText() {
    if (mText == null) {
        mText = new MutableLiveData<>();
        // 必要であれば、初期化する。
        // setValueはメインスレッドからLiveDataに通知する際に使う。
        mText.setValue("Ready?");
    }
    return mText;
}

6 . ボタン押下を契機とする、非同期の処理を追加(カウントアップ)

public void onClickButton() {
    new Thread(() -> {
        for (int i = 0; ; i++) {
            String text = "count:";
            try {
                Thread.sleep(THREAD_SLEEP_TIME);
                // postValueはメインスレッド以外からLiveDataに通知する際に使う。
                mText.postValue(text + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

7 . ◆View(Fragment)の実装を行う

8 . ViewModelProviderを取得し、TrainingViewModelのインスタンスを保持する

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // テンプレートだとonActivityCreatedでViewModelの生成をしているが、
    // 再描画されても同じViewModelを使えるようにonCreateへ移動(公式もonCreate推奨)
    mViewModel = new ViewModelProvider(this).get(TrainingViewModel.class);
}

9 . onCreateView内でレイアウトを指定する(テンプレート作成される)

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.vm1_main_fragment, container, false);
}

10 . Viewの取得とButton押下時の処理を追加

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // Viewを取得
    TextView textView = view.findViewById(R.id.vm1_text_view);
    Button mButton = view.findViewById(R.id.vm1_button);
    // Buttonの押下時の処理を追加
    mButton.setOnClickListener(v -> mViewModel.onClickButton());
}

11 . LiveDataの取得と監視、そして変更時のTextViewへの描画を行う

    // LiveDataの取得と監視
    mViewModel.getText().observe(this, new Observer<String>() {
        @Override
        public void onChanged(String s) {
            // LiveDataに変更があった時の処理を追加
            textView.setText(s);
        }
    });

Code

ViewModel 1 · atuyan39/AndroidTraining@c774d64 · GitHub

Reference

developer.android.com

developer.android.com

Memo

ViewModelは大きいテーマの一つなので、学びを深めていきたい。