From acfb98bd81a4943f46c68a15083e878e6df0115b Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Thu, 15 Dec 2022 22:57:57 +0300 Subject: [PATCH] android: Optimized chats snapshotFlow (#1578) * android: Optimized chats snapshotFlow * Concurrency test * Revert "Concurrency test" This reverts commit 911dd0c2ef8d341397e4dc0b1f8690cdb64cffaf. * Comment * Better catch --- .../chat/simplex/app/views/chat/ChatView.kt | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index d2c178fe43..6edd148c30 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -77,16 +77,23 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: () -> Unit) { } } launch { - // .toList() is important for making observation working - snapshotFlow { chatModel.chats.toList() } - .distinctUntilChanged() - .collect { chats -> - chats.firstOrNull { chat -> chat.chatInfo.id == chatModel.chatId.value }.let { - // Only changed chatInfo is important thing. Other properties can be skipped for reducing recompositions - if (it?.chatInfo != activeChat.value?.chatInfo) { - activeChat.value = it - }} + snapshotFlow { + /** + * It's possible that in some cases concurrent modification can happen on [ChatModel.chats] list. + * In this case only error log will be printed here (no crash). + * TODO: Re-write [ChatModel.chats] logic to a new list assignment instead of changing content of mutableList to prevent that + * */ + try { + chatModel.chats.firstOrNull { chat -> chat.chatInfo.id == chatModel.chatId.value } + } catch (e: ConcurrentModificationException) { + Log.e(TAG, e.stackTraceToString()) + null } + } + .distinctUntilChanged() + // Only changed chatInfo is important thing. Other properties can be skipped for reducing recompositions + .filter { it?.chatInfo != activeChat.value?.chatInfo && it != null } + .collect { activeChat.value = it } } } val view = LocalView.current