英文:
Broadcast receiver change UI
问题
是否可以从广播接收器更改Jetpack Compose用户界面中的变量?
英文:
I have searched widely but not found an answer to this question:
Is it possible to change a variable in a Jetpack compose user interface from a broadcast receiver?
答案1
得分: 4
你可以使用 DisposableEffect
和 LocalContext.current
来在Compose中注册和注销你的 BroadcastReceiver
。记得使用 rememberUpdatedState
来保持对lambda的更新引用。
这里是一个通用的Compose中的 BroadcastReceiver
示例:
@Composable
fun SystemBroadcastReceiver(
systemAction: String,
onSystemEvent: (intent: Intent?) -> Unit
) {
val context = LocalContext.current
val currentOnSystemEvent by rememberUpdatedState(onSystemEvent)
DisposableEffect(context, systemAction){
val intentFilter = IntentFilter(systemAction)
val receiver = object : BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
currentOnSystemEvent(intent)
}
}
context.registerReceiver(receiver, intentFilter)
onDispose {
context.unregisterReceiver(receiver)
}
}
}
以下是一个示例,展示了如何使用它来提取OTP:
// 这是我想要更改的值
var myOtp: String by remember { mutableStateOf("") }
SystemBroadcastReceiver(systemAction = SMS_RETRIEVED_ACTION) { intent ->
if (intent?.action == SMS_RETRIEVED_ACTION) {
val extras = intent.extras
val status = extras?.get(EXTRA_STATUS) as? Status
if (status?.statusCode == CommonStatusCodes.SUCCESS) {
val message = extras.getString(EXTRA_SMS_MESSAGE, "")
val otpReceived = Regex("[0-9]{6}").find(message)?.value
if (otpReceived != null) {
// 在这里我更改了"myOtp"的值 !!
myOtp = otpReceived
}
}
}
}
以上是示例链接:
英文:
You can make use of DisposableEffect
and LocalContext.current
for register and unregister your BroadcastReceiver
in compose. Remeber to use rememberUpdatedState
for keep an updated reference to the lambda
Here is an example of a generic BroadcastReceiver
in compose
@Composable
fun SystemBroadcastReceiver(
systemAction: String,
onSystemEvent: (intent: Intent?) -> Unit
) {
val context = LocalContext.current
val currentOnSystemEvent by rememberUpdatedState( onSystemEvent )
DisposableEffect(context, systemAction){
val intentFilter = IntentFilter( systemAction )
val receiver = object : BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
currentOnSystemEvent( intent )
}
}
context.registerReceiver( receiver, intentFilter)
onDispose {
context.unregisterReceiver(receiver)
}
}
}
Here is an example of how I used it to extract an OTP:
// this is the value I want to change
var myOtp : String by remember{ mutableStateOf("") }
SystemBroadcastReceiver(systemAction = SMS_RETRIEVED_ACTION){ intent ->
if( intent?.action == SMS_RETRIEVED_ACTION ){
val extras = intent.extras
val status = extras?.get( EXTRA_STATUS) as? Status
if( status?.statusCode == CommonStatusCodes.SUCCESS){
val message = extras.getString(EXTRA_SMS_MESSAGE, "")
val otpReceived = Regex("[0-9]{6}").find( message )?.value
if( otpReceived != null ){
// here i change the value of "myOtp" !!
myOtp = otpReceived
}
}
}
}
here is link of the above example:
答案2
得分: 1
你不能直接从广播接收器修改Compose UI。相反,你的广播接收器应该在数据层中更改一些数据 - 数据存储、偏好设置、数据库或者只是在某个存储库单例类中的内存中。然后,你应该将这些数据设置为可观察,并从Compose UI中观察它们。
英文:
You can't modify your compose ui from Broadcast receiver directly. Instead, your Broadcast receiver should change some data in your data layer - datastore, preferences, database or just in memory in some Repository singleton class. Then you should make this data observable and observe them from your compose ui.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论