Access and configure the ViewModel layer to customize data fetching, state management, and list operations.
Each component’s ViewModel lives in chatuikit-core and manages data fetching, state transitions, real-time listeners, and list operations via StateFlow. The same ViewModel is shared by both Kotlin XML Views and Jetpack Compose modules.
By default, each component creates its own ViewModel internally. To customize behavior, create the ViewModel externally using the factory and pass it to the component.
Kotlin (XML Views)
Jetpack Compose
// 1. Create the factory (optionally with a custom repository)val factory = CometChatConversationsViewModelFactory()// 2. Create the ViewModel using ViewModelProviderval viewModel = ViewModelProvider(this, factory) .get(CometChatConversationsViewModel::class.java)// 3. Configure the ViewModel before passing itviewModel.setConversationsRequestBuilder( ConversationsRequest.ConversationsRequestBuilder() .setLimit(20) .withTags(true))// 4. Pass it to the componentval conversations = findViewById<CometChatConversations>(R.id.conversations)conversations.setViewModel(viewModel)
// 1. Create the factory (optionally with a custom repository)val factory = CometChatConversationsViewModelFactory()// 2. Create the ViewModel using Compose's viewModel()val viewModel: CometChatConversationsViewModel = viewModel(factory = factory)// 3. Pass it to the componentCometChatConversations( conversationsViewModel = viewModel)
This pattern applies to all components — CometChatUsers, CometChatGroups, CometChatMessageList, CometChatCallLogs, etc. Each has a corresponding factory class.
// Collect in a lifecycle-aware scopelifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.uiState.collect { state -> when (state) { is UIState.Loading -> { /* show loading */ } is UIState.Empty -> { /* show empty */ } is UIState.Error -> { /* show error: state.exception */ } is UIState.Content -> { /* data ready: state.conversations */ } } } }}
val uiState by viewModel.uiState.collectAsState()when (uiState) { is UIState.Loading -> CircularProgressIndicator() is UIState.Empty -> Text("No conversations") is UIState.Error -> Text("Error: ${(uiState as UIState.Error).exception.message}") is UIState.Content -> { /* render list */ }}
Pass a custom ConversationsRequestBuilder to control what data the component fetches. You can set it during ViewModel creation or directly on the component:
Kotlin (XML Views)
Jetpack Compose
// Option 1: Set on the component directlyconversations.setConversationsRequestBuilder( ConversationsRequest.ConversationsRequestBuilder() .setLimit(20) .setTags(listOf("important", "pinned")) .withTags(true))// Option 2: Set on the ViewModel after creationviewModel.setConversationsRequestBuilder( ConversationsRequest.ConversationsRequestBuilder() .setLimit(20))
Perform multiple operations in a single emission — critical for performance with rapid updates:
viewModel.batch { add(newConversation1) add(newConversation2) remove(oldConversation) moveToTop(pinnedConversation)}// Only one StateFlow emission for all four operations
Subclass the ViewModel to override behavior, then inject it:
class MyConversationsViewModel( getConversationsUseCase: GetConversationsUseCase, deleteConversationUseCase: DeleteConversationUseCase, refreshConversationsUseCase: RefreshConversationsUseCase) : CometChatConversationsViewModel( getConversationsUseCase, deleteConversationUseCase, refreshConversationsUseCase) { // Override list operations to add custom behavior override fun addItem(item: Conversation) { // Example: filter out blocked users before adding val blockedUser = item.conversationWith as? User if (blockedUser?.isBlockedByMe == true) return super.addItem(item) } override fun moveItemToTop(item: Conversation) { // Example: log when a conversation is moved to top Log.d("MyVM", "Moving ${item.conversationId} to top") super.moveItemToTop(item) }}
Create it via the factory with a custom repository if needed:
val factory = CometChatConversationsViewModelFactory( repository = MyCustomRepository())
Kotlin (XML Views)
Jetpack Compose
val viewModel = ViewModelProvider(this, factory) .get(CometChatConversationsViewModel::class.java)conversations.setViewModel(viewModel)
val viewModel = viewModel<CometChatConversationsViewModel>(factory = factory)CometChatConversations( conversationsViewModel = viewModel)