見出し画像

FragmentのViewModelでカスタムApplicationクラスを利用する(Android Kotlin)

Roomを使う際にFragmentのViewModelでカスタムApplicationクラスに実装したRepositoryを渡しますが、もろもろありカスタムApplicationクラス自体をViewModelに渡すのを試していたのでそのメモです。

モチベーション

ファイルリストの取得などもViewModelの中で行いたく、色々試す中でApplicationクラスを渡してしまうのが楽(是非については置いておいて)そうだったので、それを試してみたところです。

環境

  • Android Studio Dolphin | 2021.3.1 Patch 1

    • Current Kotlin plugin version: 213-1.7.20-release-for-android-studio-AS6777.52

全体の流れ

大まかには以下のような雰囲気かと思います。

概要図

こちらのドキュメント(Roomの実装)が参考になりました。以降の説明とは順番が異なります。

カスタムApplicationクラスの実装

app/src/main/java/com/example/demo/CustomApplication.kt
※ファイルパスはAndroid Studio上からRepository Rootからのコピー

package com.example.demo

import android.app.Application
// 他Room Repositoryのimportなど

class CustomApplication: Application() {
    val applicationScope = CoroutineScope(SupervisorJob())

    // 以下はRoomを使う場合に実装するもの
    val database by lazy { DemoDatabase.getDatabase(this, applicationScope) }
    val sampleRepository by lazy { SampleRepository(database.sampleDao()) }
}

AndroidManifestの変更

app/src/main/AndroidManifest.xml
"android:name"を作成したカスタムApplicationクラス名に変更する。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:name=".CustomApplication"

〜〜 以下略 〜〜

ViewModelの実装

新たにViewModelを作成するか、既存のViewModelを以下のように"ViewModelProvider.Factory"を継承して実装する。

package com.example.demo.ui.hoge

// 必要なpackageのimport

class HogeViewModel(private val app: CustomApplication) : ViewModel() {
    // ViewModel内の実装
}

class HogeViewModelFactory(private val app: CustomApplication): ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom((HogeViewModel::class.java))) {
            @Suppress("UNCHECKED_CAST")
            return HogeViewModel(app) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

Fragmentの実装

カスタムApplicationクラスのインスタンスを渡してViewModelを作成します。

package com.example.demo.ui.hoge

// 必要なpackageのimport

class HogeFragment : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        val application = (requireActivity().application as CustomApplication)
        val hogeViewModel: HogeViewModel by viewModels {
            HogeViewModelFactory(application)
        }

        // あとはhogeViewModelのobserveを実装したりなど
    }
}

さいごに

久々にiOSとAndroidのアプリ開発をしてみましたが、iOSは以前よりすっきりしたと感じましたが、Androidはあまり変わらない(むしろ以前よりややこしい?)ように感じました。慣れの部分も大きそうですが。

ActivityとFragmentでのコンテキストの違いやMVVMでのViewModel内での実装など、もう少しシンプルに扱えたらいいのにと感じてます。
UIに関してもJetpack Composeも気になり、そっちを使うと処理との関連も扱いやすくなるのかなと妄想してたりします。

この記事が気に入ったらサポートをしてみませんか?