# Core Concepts

This page describes some of the basic concepts you'll encounter when using the Android Chat SDK.

## Calls

Many SDK methods in the client and offline libraries return a `Call` object, which is a pending operation waiting to be executed.

### Running Calls Synchronously

If you're on a background thread, you can run a `Call` synchronously, in a blocking way, using the `execute` method:

<tabs>

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

```kotlin
// Only call this from a background thread
val messageResult = channelClient.sendMessage(message).execute()
```

</tabs-item>

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

```java
// Only call this from a background thread
Result<Message> messageResult = channelClient.sendMessage(message).execute();
```

</tabs-item>

</tabs>

### Running Calls Asynchronously

You can run a `Call` asynchronously, automatically scheduled on a background thread using the `enqueue` method. The callback passed to `enqueue` will be called on the UI thread.

<tabs>

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

```kotlin
// Safe to call from the main thread
channelClient.sendMessage(message).enqueue { result: Result<Message> ->
    if (result.isSuccess) {
        val sentMessage = result.data()
    } else {
        // Handle result.error()
    }
}
```

</tabs-item>

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

```java
// Safe to call from the main thread
channelClient.sendMessage(message).enqueue((result) -> {
    if (result.isSuccess()) {
        Message sentMessage = result.data();
    } else {
        // Handle result.error()
    }
});
```

</tabs-item>

</tabs>

If you are using Kotlin coroutines, you can also `await()` the result of a `Call` in a suspending way:

```kotlin
viewModelScope.launch {
    // Safe to call from any CoroutineContext
    val messageResult = channelClient.sendMessage(message).await()
}
```

### Error Handling

Actions defined in a `Call` return `Result` objects. These contain either the result of a successful operation or the error that caused the operation to fail.

You can check whether a `Result` is successful or an error - exactly one of the following will be true for each `Result`:

<tabs>

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

```kotlin
result.isSuccess
result.isError
```

</tabs-item>

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

```java
result.isSuccess();
result.isError();
```

</tabs-item>

</tabs>

If the result was successful, you can get the contained data with `data()`. Otherwise, you can read `error()` and handle it appropriately.

<tabs>

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

```kotlin
if (result.isSuccess) {
    // Use result.data()
} else {
    // Handle result.error()
}
```

</tabs-item>

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

```java
if (result.isSuccess()) {
    // Use result.data()
} else {
    // Handle result.error()
}
```

</tabs-item>

</tabs>

Calling `data()` on a failed `Result` or calling `error()` on a successful `Result` will throw an `IllegalStateException`.


---

This page was last updated at 2026-03-05T19:01:41.981Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/v5/basics/core-concepts/](https://getstream.io/chat/docs/sdk/android/v5/basics/core-concepts/).