diff --git a/subs/compose/src/main/java/com/engineer/compose/ui/ChatActivity.kt b/subs/compose/src/main/java/com/engineer/compose/ui/ChatActivity.kt index 611c7022..b0a1756b 100644 --- a/subs/compose/src/main/java/com/engineer/compose/ui/ChatActivity.kt +++ b/subs/compose/src/main/java/com/engineer/compose/ui/ChatActivity.kt @@ -26,6 +26,7 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -77,7 +78,8 @@ fun ChatScreen( @PreviewParameter(ChatUIWithKeyboardPre::class, 1) chatUIWithKeyboard: ChatUIWithKeyboard ) { var inputValue by remember { mutableStateOf("") } - val msg by viewModel.messageList.observeAsState() + val msg by viewModel.messageList.observeAsState(ArrayList()) + val msg1 by viewModel.messages.collectAsState() val temp = provideTestChat() val kk by viewModel.kkk.observeAsState("11") @@ -89,8 +91,15 @@ fun ChatScreen( Column(modifier = Modifier.fillMaxSize()) { Text(text = kk, modifier = Modifier.size(1.dp)) + LazyColumn( + + ) { + items(msg.size, key = { it }, contentType = {msg[it].sender}) { index -> + ChatMessageItem(message = msg[index]) + } + } // 消息列表 - MessageList(messages = msg, modifier = Modifier.weight(1f)) + MessageList(messages = msg1, modifier = Modifier.weight(1f)) // 输入框和发送按钮 InputArea(inputValue = inputValue, viewModel = viewModel, messageText = { inputValue = it @@ -141,15 +150,13 @@ fun InputArea( } @Composable -fun MessageList(messages: ArrayList?, modifier: Modifier) { +fun MessageList(messages: List, modifier: Modifier) { Log.d("TAG_TAG", "msg $messages") - messages?.let { - LazyColumn( - modifier = modifier - ) { - items(messages.size, key = { it }) { index -> - ChatMessageItem(message = messages[index]) - } + LazyColumn( + modifier = modifier + ) { + items(messages.size, key = { messages[it].text }) { index -> + ChatMessageItem(message = messages[index]) } } @@ -226,4 +233,5 @@ fun ProfilePicture(resId: Int, modifier: Modifier = Modifier) { fun sendMessage(viewModel: ChatViewModel, message: String) { viewModel.query(message) +// viewModel.queryFlow(message) } diff --git a/subs/compose/src/main/java/com/engineer/compose/viewmodel/ChatViewModel.kt b/subs/compose/src/main/java/com/engineer/compose/viewmodel/ChatViewModel.kt index d77cc1e8..f2356a9d 100644 --- a/subs/compose/src/main/java/com/engineer/compose/viewmodel/ChatViewModel.kt +++ b/subs/compose/src/main/java/com/engineer/compose/viewmodel/ChatViewModel.kt @@ -6,6 +6,11 @@ import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch class ChatViewModel : ViewModel() { private val TAG = "ChatViewModel" @@ -49,42 +54,86 @@ class ChatViewModel : ViewModel() { val mockResponse = "天空呈现蓝色的原因主要与光的散射有关。当太阳光进入大气层后,大气中的气体分子和悬浮微粒会对阳光进行散射".toCharArray() val sb = StringBuffer() + sendData(sb, mockResponse) + } - val subThread = true - if (subThread) { - Thread { - sendData(sb, mockResponse, subThread) - }.start() - } else { - sendData(sb, mockResponse, subThread) + private fun sendData(sb: StringBuffer, mockResponse: CharArray) { + viewModelScope.launch { + for (c in mockResponse) { + val history = _messageList.value ?: ArrayList() + val lastMsg = history.last() + sb.append(c) + kkk.postValue(sb.toString()) + if (lastMsg.sender == "Bot") { + val newMsg = ChatMessage("Bot", sb.toString(), false) + history[history.size -1 ] = newMsg + + _messageList.value = ArrayList(history) + + } else { + val newMsg = ChatMessage("Bot", sb.toString(), false) + history.add(newMsg) + _messageList.value = history + } +// _messageList.postValue(history) + + delay(10) + Log.d(TAG, "history ${_messageList.value}") + } } -// } - private fun sendData(sb: StringBuffer, mockResponse: CharArray, subThread: Boolean) { - - for (c in mockResponse) { - val history = _messageList.value ?: ArrayList() - val lastMsg = history.last() - sb.append(c) - kkk.postValue(sb.toString()) - if (lastMsg.sender == "Bot") { - val newMsg = ChatMessage("Bot", sb.toString(), false) - history[history.size - 1] = newMsg - } else { - val newMsg = ChatMessage("Bot", sb.toString(), false) - history.add(newMsg) + private val _messages = MutableStateFlow>(emptyList()) + val messages: StateFlow> = _messages + + fun addMessage(message: ChatMessage) { + _messages.value = _messages.value + message + } + + // 更新特定 index 的消息 + fun updateMessageAt(index: Int, newMessage: ChatMessage) { + _messages.value = _messages.value.toMutableList().apply { + if (index in indices) { + this[index] = newMessage } - Log.d(TAG, "history $history") + } + } - if (subThread) { - _messageList.postValue(history) - Thread.sleep(10) - } else { - _messageList.value = history + // 模拟流式添加消息 + fun startReceivingMessages() { + var i = 0 + val mockResponse = + "天空呈现蓝色的原因主要与光的散射有关。当太阳光进入大气层后,大气中的气体分子和悬浮微粒会对阳光进行散射".toCharArray() + val sb = StringBuffer() + + + + viewModelScope.launch { + for (c in mockResponse) { + val history = _messages.value ?: ArrayList() + val lastMsg = history.last() + sb.append(c) + kkk.postValue(sb.toString()) + if (lastMsg.sender == "Bot") { + val newMsg = ChatMessage("Bot", sb.toString(), false) + updateMessageAt(history.size - 1, newMsg) + } else { + val newMsg = ChatMessage("Bot", sb.toString(), false) + addMessage(newMsg) + } + Log.d(TAG, "history $history") + delay(20) } + + } } + + fun queryFlow(userQuery: String) { + val userMsg = ChatMessage("IAM四十二", userQuery, true) + addMessage(userMsg) + startReceivingMessages() + } } \ No newline at end of file