# Thread messages (/en/realtime-media/im/build/build-groups-rooms-and-threads/threading/thread-messages/flutter)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Threads enable users to create a separate conversation from a specific message within a chat group to keep the main chat uncluttered.

    This page shows how to use the Chat SDK to send, receive, recall, and retrieve thread messages in your app.

    ## Understand the tech [#understand-the-tech-3]

    The Chat SDK provides the `ChatThreadManager`, `ChatMessage`, and `ChatThread` classes for thread messages, which allows you to implement the following features:

    ## Prerequisites [#prerequisites-3]

    Before proceeding, ensure that you meet the following requirements:

    * You have initialized the Chat SDK. For details, see [SDK quickstart](../../../get-started-sdk).
    * You understand the call frequency limit of the Chat APIs supported by different pricing plans as described in [Limitations](../../limitations).

    <CalloutContainer type="info">
      <CalloutDescription>
        The thread feature is supported by all types of [Pricing Plans](../../../reference/pricing-plan-details) and is enabled by default once you have enabled Chat in [Agora Console](https://console.agora.io/v2).
      </CalloutDescription>
    </CalloutContainer>

    ## Implementation [#implementation-3]

    This section describes how to call the APIs provided by the Chat SDK to implement thread features.

    ### Send a thread message [#send-a-thread-message-3]

    Sending a thread message is similar to sending a message in a chat group. The difference lies in the `isChatThreadMessage` field, as shown in the following code sample:

    ```dart
    // Sets `targetId` to thread ID.
    // Sets `content` to the message content.
    ChatMessage msg = ChatMessage.createTxtSendMessage(
      targetId: threadId,
      content: content,
      chatType: ChatType.GroupChat,
    );
    // Sets `isChatThreadMessage` to `true` to mark this message as a thread message.
    msg.isChatThreadMessage = true;
    //  Sends the message.
    ChatClient.getInstance.chatManager.sendMessage(msg);
    ```

    For more information about sending a message, see [Send Messages](../../build-core-messaging/messages/send-receive-messages#send-a-text-message).

    ### Receive a thread message [#receive-a-thread-message-3]

    Once a thread has a new message, all chat group members receive the `ChatThreadEventHandler#onChatThreadUpdated` callback. Thread members can also listen for the `ChatEventHandler#onMessagesReceived` callback to receive thread messages, as shown in the following code sample:

    ```dart
      // Adds the chat event handler.
      ChatClient.getInstance.chatManager.addEventHandler(
        "UNIQUE_HANDLER_ID",
        ChatEventHandler(
          onMessagesReceived: (messages) {},
        ),
      );
      // Adds the thread event handler.
      ChatClient.getInstance.chatThreadManager.addEventHandler(
        "UNIQUE_HANDLER_ID",
        ChatThreadEventHandler(
          onChatThreadUpdate: (event) {},
        ),
      );
      ...
      // Removes the chat event handler.
      ChatClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
      // Removes the chat thread event handler.
      ChatClient.getInstance.chatThreadManager.removeEventHandler("UNIQUE_HANDLER_ID");
    ```

    For more information about receiving a message, see [Receive Messages](../../build-core-messaging/messages/send-receive-messages#receive-a-message).

    ### Recall a thread message [#recall-a-thread-message-3]

    For details about how to recall a message, refer to [Recall Messages](../../build-core-messaging/messages/send-receive-messages#recall-a-message).

    Once a message is recalled in a thread, all chat group members receive the `ChatThreadEventHandler#onChatThreadUpdated` callback. Thread members can also listen for the `ChatEventHandler#onMessagesRecalled` callback, as shown in the following code sample:

    ```dart
      // Adds the chat event handler.
      ChatClient.getInstance.chatManager.addEventHandler(
        "UNIQUE_HANDLER_ID",
        ChatEventHandler(
          onMessagesRecalled: (messages) {},
        ),
      );
      // Adds the thread event handler.
      ChatClient.getInstance.chatThreadManager.addEventHandler(
        "UNIQUE_HANDLER_ID",
        ChatThreadEventHandler(
          onChatThreadUpdate: (event) {},
        ),
      );
      ...
      // Removes the chat event handler.
      ChatClient.getInstance.chatManager.removeEventHandler("UNIQUE_HANDLER_ID");
      // Removes the chat thread event handler.
      ChatClient.getInstance.chatThreadManager.removeEventHandler("UNIQUE_HANDLER_ID");
    ```

    ### Retrieve thread messages [#retrieve-thread-messages-2]

    You can retrieve thread messages locally or from the server, depending on your production environment.
    You can check `ChatConversation#isChatThread()` to determine whether the current conversation is a thread conversation.

    #### Retrieve messages of a thread from the server [#retrieve-messages-of-a-thread-from-the-server-3]

    You can call `fetchHistoryMessages` to retrieve messages of a thread from the server. The only difference between retrieving messages of a thread from the server and retrieving group messages is that a thread ID needs to be passed in for the former and a group ID is required for the latter.

    ```dart
    try {
      // The thread ID.
      String threadId = "threadId";
      // The conversation type is set to `GroupChat` as a thread belongs to a group conversation.
      ChatConversationType convType = ChatConversationType.GroupChat;
      // The number of thread messages that you expect to get on each page.
      int pageSize = 10;
      // The starting message ID for retrieving.
      String startMsgId = "";
      ChatCursorResult cursor =
          await ChatClient.getInstance.chatManager.fetchHistoryMessages(
        conversationId: convId,
        type: convType,
        pageSize: pageSize,
        startMsgId: startMsgId,
      );
    } on ChatError catch (e) {
    }
    ```

    ### Retrieve messages of a thread locally [#retrieve-messages-of-a-thread-locally-2]

    By calling [`loadAllConversations`](../../build-core-messaging/messages/manage-messages#retrieve-conversations), you can only retrieve local one-to-one chat conversations and group conversations. To retrieve messages of a thread locally, refer to the following code sample:

    ```dart
    try {
      // The thread ID.
      String threadId = "threadId";
      // The conversation type is set to `GroupChat` as a thread belongs a group conversation.
      ChatConversationType convType = ChatConversationType.GroupChat;
      ChatConversation? conversation = await ChatClient.getInstance.chatManager
            .getThreadConversation(threadId);
      // The starting message for retrieving.
      String startMsgId = "startMsgId";
      // The number of messages that you expect to retrieve on each page.
      int pageSize = 10;
      List? list = await conversation?.loadMessages(
          startMsgId: startMsgId, loadCount: pageSize);
    } on ChatError catch (e) {}
    ```

    
  
      
  
      
  
      
  
