如何使用Jetpack Compose更新我绘制的数值?

huangapple go评论84阅读模式
英文:

How can I update the value I draw with Jetpack Compose?

问题

我正在尝试创建一个Android应用程序,用于获取并显示电池百分比,但我无法使其更新。

我尝试使用updateBatteryPct函数,但由于它有延迟(否则会崩溃),它被注册为挂起,不能在onCreate中使用,因为使onCreate挂起会导致它不再是覆盖。
这是我多次尝试更新此值的其中一种方法,我甚至不确定updateBatteryPct是否会起作用。如果有人能够深入解释一下这是如何工作的,我会很感激,因为我真的不太了解。我能够使用Kotlin编码并做一些事情,但我无法做出适用于Android的任何东西。

英文:

I am trying to do an android app that gets and displays the battery percentage, but I can't get it to update.

I tried using the function updateBatteryPct but because it has a delay (else it crashes) it is registered as suspend it cannot be used in onCreate because making onCreate suspend causes it to not be an override anymore.
This is one of my many tries to update this value, I am not even sure that updateBatteryPct will even work. I would appreciate if someone could explain me in depth how this works bc I dont understad really everything. I can code in Kotlin and do stuff but I can't do anything that works for android.

  1. class MainActivity : ComponentActivity() {
  2. var batteryStatus: Intent? = null
  3. var batteryPct: MutableState<Int> = mutableStateOf(0)
  4. override fun onCreate(savedInstanceState: Bundle?) {
  5. super.onCreate(/* savedInstanceState = */ savedInstanceState)
  6. setContent {
  7. this.batteryStatus = getBatteryStatusReceiver()
  8. this.batteryPct = remember {
  9. mutableStateOf(0)
  10. }
  11. BatterySaverAppTheme {
  12. // A surface container using the 'background' color from the theme
  13. Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
  14. getBatteryPct(this.batteryStatus, this.batteryPct)
  15. DisplayBatteryPercentage(batteryPercentage = this.batteryPct)
  16. }
  17. }
  18. }
  19. }
  20. suspend fun updateBatteryPct () {
  21. while (true) {
  22. getBatteryPct(this.batteryStatus, this.batteryPct)
  23. delay(1000)
  24. Log.d("customTest", "updateBatteryPct: Looping")
  25. }
  26. }
  27. }
  28. class BatteryManagerBroadcastReceiver(
  29. private val onReceiveIntent: (Intent) -> Unit,
  30. ) : BroadcastReceiver() {
  31. override fun onReceive(context: Context, intent: Intent) {
  32. onReceiveIntent(intent)
  33. }
  34. }
  35. @Composable
  36. fun updateBatteryPct(batteryStatus: Intent?, batteryPct: MutableState<Int>) {
  37. while (true) {
  38. getBatteryPct(batteryStatus, batteryPct)
  39. DisplayBatteryPercentage(batteryPercentage = batteryPct)
  40. }
  41. }
  42. fun getBatteryPct(batteryStatus: Intent?, batteryPct: MutableState<Int>){
  43. batteryPct.value = batteryStatus?.let { intent ->
  44. val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
  45. val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
  46. level * 100 / scale
  47. }!!
  48. }
  49. @Composable
  50. fun getBatteryStatusReceiver(): Intent? {
  51. val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
  52. LocalContext.current.applicationContext.registerReceiver(null, ifilter)
  53. }
  54. return batteryStatus
  55. }
  56. @Composable
  57. fun DisplayBatteryPercentage(batteryPercentage: MutableState<Int>) {
  58. Column(Modifier.padding(16.dp)) {
  59. Text("battery is at ${batteryPercentage.value}%") }
  60. }

答案1

得分: 2

更好的方法是使用带有副作用的BroadcastReceiver进行注册。

类似这样的:

  1. @Composable
  2. fun SystemBroadcastReceiver(
  3. systemAction: String,
  4. onSystemEvent: (intent: Intent?) -> Unit
  5. ) {
  6. // 在 UI 树的这一部分获取当前的上下文
  7. val context = LocalContext.current
  8. // 安全地使用传递给函数的最新 onSystemEvent lambda
  9. val currentOnSystemEvent by rememberUpdatedState(onSystemEvent)
  10. // 如果上下文或者 systemAction 发生变化,注销并重新注册
  11. DisposableEffect(context, systemAction) {
  12. val intentFilter = IntentFilter(systemAction)
  13. val broadcast = object : BroadcastReceiver() {
  14. override fun onReceive(context: Context?, intent: Intent?) {
  15. currentOnSystemEvent(intent)
  16. }
  17. }
  18. context.registerReceiver(broadcast, intentFilter)
  19. // 当效果离开 Composition 时,移除回调
  20. onDispose {
  21. context.unregisterReceiver(broadcast)
  22. }
  23. }
  24. }

然后在你的 composable 中只需更新该值:

  1. var battery by remember { mutableStateOf(0) }
  2. SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus ->
  3. val batteryPct: Float? = batteryStatus?.let { intent ->
  4. val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
  5. val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
  6. level * 100 / scale.toFloat()
  7. }
  8. battery = batteryPct!!.toInt()
  9. }
英文:

It is better to register the BroadcastReceiver with a side effect.

Something like:

  1. @Composable
  2. fun SystemBroadcastReceiver(
  3. systemAction: String,
  4. onSystemEvent: (intent: Intent?) -> Unit
  5. ) {
  6. // Grab the current context in this part of the UI tree
  7. val context = LocalContext.current
  8. // Safely use the latest onSystemEvent lambda passed to the function
  9. val currentOnSystemEvent by rememberUpdatedState(onSystemEvent)
  10. // If either context or systemAction changes, unregister and register again
  11. DisposableEffect(context, systemAction) {
  12. val intentFilter = IntentFilter(systemAction)
  13. val broadcast = object : BroadcastReceiver() {
  14. override fun onReceive(context: Context?, intent: Intent?) {
  15. currentOnSystemEvent(intent)
  16. }
  17. }
  18. context.registerReceiver(broadcast, intentFilter)
  19. // When the effect leaves the Composition, remove the callback
  20. onDispose {
  21. context.unregisterReceiver(broadcast)
  22. }
  23. }
  24. }

Then in your composable just update the value:

  1. var battery by remember { mutableStateOf(0) }
  2. SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus ->
  3. val batteryPct: Float? = batteryStatus?.let { intent ->
  4. val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
  5. val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
  6. level * 100 / scale.toFloat()
  7. }
  8. battery = batteryPct!!.toInt()
  9. }

huangapple
  • 本文由 发表于 2023年2月27日 19:31:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75579909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定