SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門

【Android開発中級者に贈るJetpack入門】UIのデータを管理するViewModelとは?

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門 第1回


  • X ポスト
  • このエントリーをはてなブックマークに追加

ViewModelの利用

 では、これらのViewModelをアクティビティで利用するコードを見ていきましょう。

ViewModelはフィールドで定義しonCreate()で用意

 先述のように、図3を見ると、ViewModelは、その相方となるアクティビティで生成されると、その後はアクティビティが消滅するまで存在することになります。そこで、アクティビティでは、相方となるViewModelクラスをフィールドで用意しておき、onCreate()で実際のオブジェクトを用意します。これは、例えば、Javaではリスト3のようなコードになります。

リスト3:足し算アプリのMainActivity(Java版)
public class MainActivity extends AppCompatActivity {
	private MainViewModel _mainViewModel;  // (1)
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		:
		ViewModelProvider provider = new ViewModelProvider(MainActivity.this);  // (2)
		_mainViewModel = provider.get(MainViewModel.class);  // (3)

		EditText etNum1 = findViewById(R.id.etNum1);  // (4)
		etNum1.setText(_mainViewModel.getNum1Str());  // (4)
		EditText etNum2 = findViewById(R.id.etNum2);  // (4)
		etNum2.setText(_mainViewModel.getNum2Str());  // (4)
		TextView tvAnswer = findViewById(R.id.tvAnswer);  // (4)
		tvAnswer.setText(_mainViewModel.getAnsStr());  // (4)
	}
	:
}

 リスト3の(1)が、リスト1のMainViewModelをフィールドとして定義しているコードです。そして、実際にそのオブジェクトを取得しているのが、(2)と(3)です。ViewModelオブジェクトは、そのクラスを直接newするのではなく、まず、(2)のようにViewModelProviderをnewします。その際、引数に、コンテキストとしてアクティビティオブジェクトを渡します。このViewModelProviderにアクティビティオブジェクトを渡すことで、生成されるViewModelとこのアクティビティがペアになります。

 その後、newされたViewModelProviderオブジェクトのget()メソッドを実行することで、ViewModelオブジェクトを取得します。それが、(3)です。その際、取得するViewModelクラスを渡します。

onCreate()でViewModelのデータと画面部品を紐付ける

 ここでひとつ注意点があります。リスト3の(2)と(3)のように生成したViewModelオブジェクトを利用して、同じくonCreate()において画面部品とViewModel内のデータを紐づけておく必要があります。それが(4)です。num1とnum2の値を入力するEditTextに対してそれぞれgetNum1Str()とgetNum2Str()の値を、答え表示TextViewに対してgetAnsStr()の値を設定しています。

 その後は、例えば、計算ボタンをクリックした時の処理も、リスト4の(1)と(2)のように単に入力データを_mainViewModelにセットし、(3)のようにgetAnsStr()をtvAnswerにセットするだけで、問題なく表示されるようになります。しかも、画面を回転させても、図4のように値を保持したままとなります。

リスト4:足し算アプリの計算ボタンの処理(Java版)
public void onBtCalcClick(View view) {
	EditText etNum1 = findViewById(R.id.etNum1);
	String num1Str = etNum1.getText().toString();
	_mainViewModel.setNum1Str(num1Str);  // (1)
	EditText etNum2 = findViewById(R.id.etNum2);
	String num2Str = etNum2.getText().toString();
	_mainViewModel.setNum2Str(num2Str);  // (2)
	TextView tvAnswer = findViewById(R.id.tvAnswer);
	tvAnswer.setText(_mainViewModel.getAnsStr());  // (3)
}
図4: ViewModelを利用すると画面の回転でも結果表示が消えない
図4: ViewModelを利用すると画面の回転でも結果表示が消えない

KotlinではviewModels()を利用

 では、KotlinコードでViewModelを利用する場合は、アクティビティにはどのようなコードを書けばいいのかというと、Javaコードと同じようにViewModelProviderを利用したコードでも問題なく動作します。すなわち、リスト3の(2)と(3)をKotlinコードに置き換えたコードです。一方、Kotlinの場合は、リスト5のように、もっと簡潔に記述できます。

リスト5:足し算アプリのMainActivity(Kotlin版)
class MainActivity : AppCompatActivity() {
	private val _mainViewModel by viewModels<MainViewModel>()  // (1)

	override fun onCreate(savedInstanceState: Bundle?) {
		:
		val etNum1 = findViewById<EditText>(R.id.etNum1)  // (2)
		etNum1.setText(_mainViewModel.getNum1Str())  // (2)
		:  // (2)
	}
	:
}

 Kotlinでは、ViewModelオブジェクトを簡単に取得するための記述として、以下が用意されています。

 by viewModels<…>()

 リスト5の(1)のように、プロパティとしてViewModelオブジェクトを定義しておき、その続きに、上記コードを記述するだけで、自動的にViewModelオブジェクトを生成してくれます。その際、どのクラスのViewModelを生成するのかを、ジェネリクスとして型指定します。

 ただし、このviewModels()を利用するためには、activity-ktxライブラリを追加しておく必要があります。これは、build.gradle(Module)ファイルのdependenciesに以下の1行を追加することで可能となります。

 implementation "androidx.activity:activity-ktx:1.5.1"

 なお、「1.5.1」というバージョンは、原稿執筆時点での最新安定版です。1.6.0がリリースされているという警告が表示されますが、まだRC版ですので、現時点では1.5.1がおすすめです。

 追加後は、画面右上に表示される[Sync Now]をクリックして、再ビルドを行うことを忘れないでください(図5)。

図5: build.gradle改変後は[Sync Now]をクリック
図5: build.gradle改変後は[Sync Now]をクリック

 ところで、リスト5の(2)は、リスト3の(4)のJavaコードをそのままKotlinコードに置き換えたものです。Kotlinでも、onCreate()で紐付けを行っておくことを忘れないようにしてください。そのようにしておくだけで、計算ボタンの処理については、リスト4のonBtCalcClick()メソッドのコードを、そのままKotlinに置き換えたコードで問題なく動作します。

まとめ

 Android Jetpackについて紹介していく本連載の第1回は、いかがでしたでしょうか。初回を飾るテーマは、UIに必要なデータ処理を担うViewModelを紹介しました。ViewModelを導入することで、アクティビティは本来のUIの処理に集中できるようになります。

 次回は、データベース処理を容易に実装できるライブラリであるRoomを紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16909 2023/02/17 16:41

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング