LoginSignup
0
0

More than 1 year has passed since last update.

【Jetpack Compose】StateFlow でカウンターを作ってみる

Last updated at Posted at 2022-06-20

Composable 入れ子の更新具合を確認します。

@HiltViewModel
class SampleViewModel @Inject constructor() : ViewModel() {

  private val _count = MutableStateFlow(0)
  val count = _count.asStateFlow()

  fun inc() {
    _count.update { count -> count + 1 }
  }

}

👉 StateFlow の View への公開

@Composable
fun SampleScreen(
  viewModel: SampleViewModel = hiltViewModel()
) {

  val count: Int by viewModel.count.collectAsState()

  Column(
   Modifier.fillMaxSize(),
   Arrangement.Center,
   Alignment.CenterHorizontally
  ) {
    Text("$count")
    Button(onClick = { viewModel.inc() }) {
      Timber.d("Button composed.")
      Icon(Icons.Filled.Add, null)
    }
  }
  
}

何回クリックしても Button の compose は一回。

Button composed.

Button 内に影響される Text() を追加する。

@Composable
fun SampleScreen(
  viewModel: SampleViewModel = hiltViewModel()
) {

  val count: Int by viewModel.count.collectAsState()

  Column(
    Modifier.fillMaxSize(),
    Arrangement.Center,
    Alignment.CenterHorizontally
  ) {
    Text("$count")
    Button(onClick = { viewModel.inc() }) {
      Timber.d("Button composed.")
      Icon(Icons.Filled.Add, null)
      Text("$count") // *
    }
  }
  
}

クリックするたびに、Button は compose される。

Button composed.
Button composed.
Button composed.
Button composed.
Button composed.
Button composed.
...

ネストした Composable

@Composable
fun SampleScreen(
  viewModel: SampleViewModel = hiltViewModel()
) {

  val count: Int by viewModel.count.collectAsState()

  Column(
    Modifier.fillMaxSize(),
    Arrangement.Center,
    Alignment.CenterHorizontally
  ) {
    Text("$count")
    ChildA(onClick = { viewModel.inc() })
    ChildB(count, onClick = { viewModel.inc() })
  }

}

@Composable
fun ChildA(onClick: () -> Unit) {

  Button(onClick = onClick) {
    Timber.d("ChildA composed.")
    Icon(Icons.Filled.Add, null)
  }

}

@Composable
fun ChildB(count: Int, onClick: () -> Unit) {

  Button(onClick = onClick) {
    Timber.d("ChildB composed.")
    Icon(Icons.Filled.Add, null)
    Text("$count")
  }

}

ChildA は初回のみ compose されます。 ChildA、ChildB どちらのボタンを押しても re-compose されるのは、ChildB のみです。

D: ChildA composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.
D: ChildB composed.

無駄な描画をしない!

すごいです、Jetpack Compose!!

👉 JakeWharton/timber: A logger with a small, extensible API which provides utility on top of Android's normal Log class.
👉 Jetpack Compose State Guideline. This article presents the information… | by takahirom | Medium
👉【Jetpack Compose】Icon() や Image() で ImageVector をより便利に使う

0
0
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
0
0