Android Jetpack 在 Composable 之间传递数据

时间:2021-06-30 19:02:55

标签: multithreading kotlin-coroutines android-jetpack android-viewmodel android-jetpack-compose

我正在尝试在我的 Jetpack Composables 中传递不断更新的变量“消息”。我有一个可拖动的框来跟踪框的坐标,但我正在尝试通过 TCP 连接发送实时数据。但是,我注意到可拖动框的当前坐标没有传递到另一个可组合或套接字 - 尽管由于我拖动框而导致消息不断变化,但只传递了相同的值。此外,按下 dataSendButton() 的那一刻,createDragImage() 及其可拖动框停止动画/运行。

var message = "" // global Android send message


class MainActivity : ComponentActivity() {
    private var textView: TextView? = null  
        dataSendButton()
        createDragImage()
        ...
        }
    }
}
    
@Composable
fun createDragImage(){
        val context = LocalContext.current
        ...
            Box() {
                var offsetX by remember { mutableStateOf(0f) }
                var offsetY by remember { mutableStateOf(0f) }

                Box(
                    Modifier
                        .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                        .background(Color.Transparent)
                        .size(150.dp)
                        .border(BorderStroke(4.dp, SolidColor(Color.Red)))
                        .pointerInput(Unit) {
                            detectDragGestures { change, dragAmount ->
                                change.consumeAllChanges()
                                offsetX = someConstantX
                                offsetY += dragAmount.y
                                message = offsetY.toString()
...

@Composable
fun dataSendButton() {
                val context = LocalContext.current
                ...
                Button(
                    onClick = {
                    // **ISSUE: message in this composable is not getting updated with message value from createDragImage()
                        val b1 = MainActivity.TCPconnector_client(context, message)
                        b1.execute()
                    },

                {
                    Text(text = "Send Data", color = Color.White, fontSize = 20.sp)
                }

            }
        }

    }
}
    

1 个答案:

答案 0 :(得分:0)

这是因为这不是您在 Compose 中存储状态的方式。

更改变量的声明。

var message by mutableStateOf(...)

然后对它的更改将触发重新组合,因此其余代码应保持不变。始终建议将状态持有者存储在视图模型中,并改为传递视图模型。

这是一个带有视图模型的工作代码

class MainActivity : ComponentActivity() {
    private var textView: TextView? = null  
    val vm by viewmodels<MViewModel>()

        dataSendButton(vm.message, vm:: onMessageChange)
        createDragImage(vm.message)
        ...
        }
    }
}
    
@Composable
fun createDragImage(message: String, onMessageChange: (String) -> Unit){
        val context = LocalContext.current
        ...
            Box() {
                var offsetX by remember { mutableStateOf(0f) }
                var offsetY by remember { mutableStateOf(0f) }

                Box(
                    Modifier
                        .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                        .background(Color.Transparent)
                        .size(150.dp)
                        .border(BorderStroke(4.dp, SolidColor(Color.Red)))
                        .pointerInput(Unit) {
                            detectDragGestures { change, dragAmount ->
                                change.consumeAllChanges()
                                offsetX = someConstantX
                                offsetY += dragAmount.y
                                onMessageChange (offsetY.toString())
...

@Composable
fun dataSendButton(message: String) {
                val context = LocalContext.current
                ...
                Button(
                    onClick = {
                    // **ISSUE: message in this composable is not getting updated with message value from createDragImage() // This seems to be an error. Calling a Composable from onClick?
                        val b1 = MainActivity.TCPconnector_client(context, message)
                        b1.execute()
                    },

                {
                    Text(text = "Send Data", color = Color.White, fontSize = 20.sp)
                }

            }
        }

    }
}

class MViewModel: ViewModel(){
var message by mutableStateOf("")
private set //do not allow external modifications to ensure consistency

fun onMessageChange (newMessage: String){
message = newMessage
}

}

请注意,这是进行此类实现的理想方式。但是,对于您的具体情况,如果您不需要在其他任何地方访问它,只需按照答案第二行中的描述更改声明即可

谢谢