2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】Jetpack ComposeでViewModelを入れてみた

Posted at

背景

前回jetpack composeでカウントアップアプリを作成したときに、クリック回数を記憶する変数をActivityに直書きしていました。
↓前回製作したもの

ただ、画面の回転やライフサイクルの働きによりactivity内の一時的に保存している情報が破棄されてしまい、リセットされる危険性があるためViewModelにカウントアップの処理を移動させました。

今回の変更

クリック回数計算をviewModelに託す

Before

MainActivity.kt
  var countTapStar by remember {
            mutableStateOf(0)
        }
        var countTapTriangle by remember {
            mutableStateOf(0)
        }

After

MainActivity.kt
    val countTapStar by countViewModel.starCount.observeAsState(initial = 0)
    val countTapTriangle by countViewModel.triangleCount.observeAsState(initial = 0)
     
CountViewModel.kt

class CountViewModel : ViewModel() {
    //MutableLiveDataで監視と変更ができる値を宣言する
    val starCount = MutableLiveData(0)
    val triangleCount = MutableLiveData(0)
    //宣言した変数の値を読み込んで上書きする
    fun starCountUp() {
        val starPlusCount = starCount.value ?: 0
        starCount.value = starCount.value?.plus(1)
    }

    fun triangleCountUp() {
        val trianglePlusCount = triangleCount.value ?: 0
        triangleCount.value = triangleCount.value?.plus(1)
    }
}

MainActivity.ktの全体像

MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Column {
                showImage()
            }
        }
    }
}

@Composable
fun showImage(
    countViewModel: CountViewModel = viewModel()
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.SpaceEvenly,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        //viewModelの変数を結びつけながら初期値設定する
        val countTapStar by countViewModel.starCount.observeAsState(initial = 0)
        val countTapTriangle by countViewModel.triangleCount.observeAsState(initial = 0)
        Row {
            Text(
                text = "Star:$countTapStar ,",
                fontSize = 16.sp,
                color = colorResource(id = R.color.cherry_rose)
            )
            Text(
                text = "Triangle:$countTapTriangle",
                fontSize = 16.sp,
                color = colorResource(id = R.color.moegi)
            )
        }
        Row {
            Image(
                painter = painterResource(id = R.drawable.icon_svg), contentDescription = "",
                modifier = Modifier
                    .size(108.dp)
                    .border(1.dp, color = colorResource(id = R.color.moegi))
                    //Before
                    // .clickable { countTapStar++ },
                    .clickable { countViewModel.starCountUp() },
                contentScale = ContentScale.Crop,
            )
            Image(
                painter = painterResource(id = R.drawable.triangle),
                contentDescription = "",
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .size(108.dp)
                    //Before
                    // .clickable { countTapTriangle++ })
                    .clickable { countViewModel.triangleCountUp() })
        }
    }
}

実際の動き

よくなった点

画面回転やライフサイクルによるデータリセット対策ができました。 背景でも記載した通り、スマホには外的要因によってデータが破棄される危険性を孕んでいます。その対策として画面回転などをしても破棄されないviewModelに値を記憶しておくことで、アプリの安全性を高めることができました。

もう一つは役割分担することでプログラムの可読性が上がりました。 画面宣言しているパートとロジックパートが一緒になっているプログラムは、読みづらいうえに些細な変更に対して弱いプログラムになってしまいます。
上司から「このプログラムに既存の機能に影響がないように機能を追加してくれ」と頼まれふたを開けてみたら、たくさんのメソッドがあるうえにこうしたコードだったら気絶するでしょう。

まだアーキテクチャについては学習中ですが、学習する前と後ではコーディングの正確性がまるで違うことを実感しています。

参考サイト

Repository

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?