AndroidでViewModelを使用するメリット
本稿ではAndroidでViewModelを使用するメリットを説明します。
ViewModelのメリット
今までは画面回転などでActivityが破棄される場合を考慮して実装していたのが、
ViewModelを使うことで、その部分を考慮せずに記述できるようになります。
(ライフサイクルを意識せずに記述していくことが可能になります)
また、ViewとViewModelの役割が明確に分かれていき、
FatなActivityやFragmentになるのを防ぐことができます。
LiveDataのメリット
ViewModelとあわせて使用することの多いLiveDataのメリットも説明します。
LiveDataLには以下のようなメリットがあります。
- メモリリークしない
- データの状態を受け取りUIに自動反映できる
- ActivityがBackStackにある時はデータ通知されない
- 自分でライフサイクル管理しなくていい
- BackStackがActiveになった瞬間に最新のデータを受け取れる
- シングルトンでラップすれば色々な場所からLiveDataを読み込める
ViewModelとLiveDataLiveDataを使用したサンプル
Activityの実装
public class MainActivity{
private ViewModel mViewModel = null;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
mViewModel = ViewModelProviders.of(this).get(ViewModel.class);
//LiveDataに既にObserversがあるかどうかを確認。
// LiveDataに既にデータセットがある場合Observersに配信される。
if (mViewModel.getItems().hasObservers()) {
return;
}
mViewModel.getItems().observe(this, new Observer<List() {
@Override
public void onChanged(@Nullable final List result) {
// UI更新
if (result != null) {
//ViewModelのバックグラウンド処理を実行
mViewModel.loadItems();
} else {
// エラー処理
}
}
});
} catch (IllegalArgumentException e) {
// エラー処理
}
}
}
ViewModelの実装
public class ViewModel extends AndroidViewModel {
private final MutableLiveData<List> mLiveData = new MutableLiveData<>();
public ViewModel(@NonNull Application application) {
super(application);
}
public LiveData<List> getItems() {
return mLiveData;
}
public void loadItems() {
new ViewModel.LoadTask(mLiveData).execute();
}
private static class LoadTask extends AsyncTask<Void, Void, Void> {
private final MutableLiveData<List> mBackgroundLiveData;
LoadTask(MutableLiveData<List> liveData) {
mBackgroundLiveData = liveData;
}
@Override
protected Void doInBackground(Void... voids) {
Context context = SampleApplication.get().getApplicationContext();
Uri uri = Uri.parse("content://com.hogehoge.smple.provider/categories").buildUpon().build();
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor == null) {
return null;
}
List categories = new ArrayList<>();
if (cursor.moveToFirst()) {
do {
try {
categories.add(Category.class.getConstructor(Cursor.class).newInstance(cursor));
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
//エラー
}
} while (cursor.moveToNext());
}
cursor.close();
if (categories.isEmpty()) {
mBackgroundLiveData.postValue(null);
return null;
}
mBackgroundLiveData.postValue(categories);
return null;
}
}
}
スポンサーリンク