# Getting Started

The **UI Components** library includes pre-built Android Views to easily load and display data from the Stream Chat API.

<admonition type="info">

Already using Jetpack Compose? Check out our [Compose UI Components](/chat/docs/sdk/android/v6/compose/overview/).

</admonition>

First things first, you have to initialize the `ChatClient` in your application.
This is the main entry point for all the chat functionalities.
Typically you would initialize the `ChatClient` in your `Application` class.

```kotlin
ChatClient.Builder("YOUR_API_KEY", context)
    // Set other configurations
    .build()

// Static reference to initialised client
val client = ChatClient.instance()
```

## Connecting a User

Once you have the `ChatClient` initialised, you can connect a user to the chat.

Let's say you have a `User` model:

```kotlin
val user = User(
    id = "bender",
    name = "Bender",
    image = "https://bit.ly/321RmWb",
)
```

Then you can call the `connectUser` method with either a JWT token or a `TokenProvider` to connect the user to the chat.

Here is an example of how to connect a user to the chat with a JWT token:

```kotlin
val token = "CHAT_USER_TOKEN"
client.connectUser(user, token).enqueue { result ->
    when (result) {
        is Result.Success -> {
            // Logged in
            val loggedInUser: User = result.value.user
            val connectionId: String = result.value.connectionId
        }
        is Result.Failure -> {
            // Handle error
            val error = result.value
        }
    }
}
```

Here is an example of how to connect a user to the chat with a `TokenProvider`:

```kotlin
val tokenProvider = object : TokenProvider {
    // Make a request to your backend to generate a valid token for the user.
    // It is expected that "yourTokenService.getToken" never throws an exception.
    // If the token cannot be loaded, it should return an empty string.
    override fun loadToken(): String = yourTokenService.getToken(user)
}
client.connectUser(user, tokenProvider).enqueue { /* ... */ }
```

<admonition type="note">

Please ensure that the `TokenProvider.loadToken` implementation never throws an exception.
If the token cannot be loaded, it should return an empty string.

</admonition>

## Lifecycle Management

Most commonly, you would want to call `ChatClient#connectUser` when the user logs in and `ChatClient#disconnect` when the user logs out.

<admonition type="note">

Please take into account that the `ChatClient` cannot survive a process death.
When the app process gets killed with the logged-in user, you will need to call `ChatClient#connectUser` again to re-establish the connection.

</admonition>

To handle those scenarios, you could define some `UserRepository` in your application that would be responsible for storing the logged-in user until the user logs out.

```kotlin
interface UserRepository {
    fun getCurrentUser(): User?
    fun setCurrentUser(user: User)
    fun clearCurrentUser()
}
```

<admonition type="note">

Please note that the `UserRepository` is just an example.
You can name it whatever you want and use any storage mechanism for the implementation (for example `SharedPreferences`, `Room`, etc.).
The main idea is to have a storage which will be able to provide the logged-in user when the app restarts after a process death.

</admonition>

Then when the user logs in, you would call `ChatClient#connectUser` and store the user in the `UserRepository`.

```kotlin
val user = User(/* ... */)
client.connectUser(user, tokenProvider).enqueue { result ->
    if (result is Result.Success) {
        userRepository.setCurrentUser(result.value.user)
    } else if (result is Result.Failure) {
        // Handle error
    }
}
```

When the user logs out, you would call `ChatClient#disconnect` and clear the user from the `UserRepository`.

```kotlin
client.disconnect(flushPersistence = true).enqueue { result ->
    userRepository.clearCurrentUser()
    // Handle result
}
```

Please note that you should also call `ChatClient#connectUser` when the Application restarts after a process death and there is a logged-in user in the `UserRepository`.

```kotlin
val user = userRepository.getCurrentUser()
if (user != null) {
    client.connectUser(user, tokenProvider).enqueue { /* ... */ }
}
```

## UI Components

| Channels Screen                                                                   | Messages Screen                                                                   |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| ![Channel List component](@chat-sdk/android/v6/_assets/sample-channels-light.png) | ![Message List component](@chat-sdk/android/v6/_assets/sample-messages-light.png) |

This library builds on top of the offline library, and provides [ViewModels](#viewmodels) for most Views to easily populate them with data and handle input events.

The [sample app](#sample-app) showcases the UI components in action.

See the individual pages of the components to learn more about them.

**Channel components**:

- [Channel List Screen](/chat/docs/sdk/android/v6/ui/channel-components/channel-list-screen/)
- [Channel List](/chat/docs/sdk/android/v6/ui/channel-components/channel-list/)
- [Channel List Header](/chat/docs/sdk/android/v6/ui/channel-components/channel-list-header/)

**Message components**:

- [Message List Screen](/chat/docs/sdk/android/v6/ui/message-components/message-list-screen/)
- [Message List](/chat/docs/sdk/android/v6/ui/message-components/message-list/)
- [Message List Header](/chat/docs/sdk/android/v6/ui/message-components/message-list-header/)
- [Message Composer](/chat/docs/sdk/android/v6/ui/message-components/message-composer/)
- [System Attachments Picker](/chat/docs/sdk/android/v6/ui/message-components/system-attachments-picker/)

**Utility components**:

- [Pinned Message List](/chat/docs/sdk/android/v6/ui/utility-components/pinned-message-list/)
- [Search Views](/chat/docs/sdk/android/v6/ui/utility-components/search-view/)
- [Attachment Gallery](/chat/docs/sdk/android/v6/ui/utility-components/attachment-gallery/)

## Checklist

For a successful integration of our UI Components, follow these steps:

1. Dependency. Add the dependency to your app, as described on the [Dependencies](/chat/docs/sdk/android/v6/basics/dependencies#ui-components/) page.
2. Set up the `ChatClient`. Learn how to initialize the ChatClient in the [Chat Client documentation](/chat/docs/android/#chat-client/).
3. Handle user connection. Read how to connect a user in the [Connecting the User guide](/chat/docs/android/init_and_users/#connecting-the-user/) and learn about User Tokens in the [Tokens and Authentication guide](/chat/docs/android/tokens_and_authentication/).
4. State and Offline. Using the `StatePlugin` is mandatory if you want to use our UI Components. Read the [State Overview](/chat/docs/sdk/android/v6/client/guides/state-overview/) page for more information. Also, consider adding [offline support](/chat/docs/sdk/android/v6/client/guides/offline-support/) for better UX.
5. Theme. Since this library uses Material elements, make sure that you use a Material theme in your application before adding the components. This means that your app's theme should extend a theme from `Theme.MaterialComponents`, and not `Theme.AppCompat`. Find a correct example **below**. If you want to keep using an `AppCompat` theme for styling, you can inherit from a [Bridge Theme](https://m2.material.io/develop/android/docs/getting-started#bridge-themes) to support using Material based components.

```xml
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
```

<admonition type="note">

Check out our [sample app](#sample-app) for a quick start in using our UI Components.

</admonition>

## ViewModels

Most UI components come with their own ViewModels. These are used to easily connect them to the client to fetch data and perform actions.

These are Jetpack [ViewModels](https://developer.android.com/topic/libraries/architecture/viewmodel), so they allow the components to retain data across configuration changes. It's your responsibility to create these in the correct scope, usually in a Fragment or Activity.

For example, if you've added a `MessageListView` to your layout, you can create a corresponding ViewModel like this:

<tabs>

<tabs-item value="kotlin" label="Kotlin">

```kotlin
// 1
val factory = MessageListViewModelFactory(cid = "messaging:123")
// 2
val viewModel: MessageListViewModel by viewModels { factory }
// 3
viewModel.bindView(messageListView, viewLifecycleOwner)
```

</tabs-item>

<tabs-item value="java" label="Java">

```java
// 1
ViewModelProvider.Factory factory = new MessageListViewModelFactory
        .Builder()
        .cid("messaging:123")
        .build();
ViewModelProvider provider = new ViewModelProvider(this, factory);
// 2
MessageListViewModel viewModel = provider.get(MessageListViewModel.class);
// 3
MessageListViewModelBinding.bind(viewModel, messageListView, getViewLifecycleOwner());
```

</tabs-item>

</tabs>

1. Create the `ViewModel` factory, providing any necessary parameters.
2. Fetch a ViewModel with Android ViewModel APIs, passing in the factory to be used.
3. Call the `bindView` method of the SDK to connect the View and ViewModel, passing in the appropriate `LifecycleOwner`.

`bindView` performs two-way binding: it sets up observers that push data from the ViewModel to the View, and sets up listeners that forward input events from the View to the ViewModel.

<admonition type="note">

If you're setting your own listeners on the Views, make sure to do it _after_ calling `bindView`.

</admonition>

You can learn more about setting up each UI component on their individual documentation pages.

## Sample App

The [UI Components sample app](https://github.com/GetStream/stream-chat-android/tree/v6/stream-chat-android-ui-components-sample) is an open source, fully functional messaging application. It features threads, reactions, typing indicators, optimistic UI updates and offline storage. All built on top of our UI components.

| ![Sample app login screen](@chat-sdk/android/v6/_assets/sample-login-dark.png) | ![Sample app messages screen](@chat-sdk/android/v6/_assets/sample-messages-dark.png) |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |

## Customization

The UI components offer customization options via XML attributes as well as instance methods. You can check the individual pages of the components for more details about this. Components can also be customized globally via themes and style transformations. The [Theming](/chat/docs/sdk/android/v6/ui/general-customization/theming/) page describes all the available styling options for the SDK in detail.

You can also use the [`ChatUI`](/chat/docs/sdk/android/v6/ui/general-customization/chatui/) object to customize the behavior of the UI Components. For example, it allows you to override fonts, add your own URL signing logic, or add custom avatar loading logic.


---

This page was last updated at 2026-04-17T17:33:30.696Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/v6/ui/overview/](https://getstream.io/chat/docs/sdk/android/v6/ui/overview/).