Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

## stream-chat-android-compose
### 🐞 Fixed
- Ensure `isAppInForegroundAsState` lifecycle observer removal occurs on the main thread. [#6033](https://github.com/GetStream/stream-chat-android/pull/6033)

### ⬆️ Improved

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package io.getstream.chat.android.compose.util

import android.os.Handler
import android.os.Looper
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
* Produces a [State] that indicates whether the app is currently in the foreground.
Expand All @@ -38,7 +42,31 @@ internal fun isAppInForegroundAsState(): State<Boolean> {
else -> value
}
}
lifecycle.addObserver(observer)
awaitDispose { lifecycle.removeObserver(observer) }
withContext(Dispatchers.Main.immediate) {
lifecycle.addObserver(observer)
}
Comment thread
aleksandar-apostolov marked this conversation as resolved.
awaitDispose {
lifecycle.removeObserverOnMainThread(observer)
}
}
}

/**
* Removes a lifecycle observer on the main thread.
*
* [Lifecycle.removeObserver] must be called on the main thread. During normal app execution
* this is typically the case, but in instrumentation tests this might be called on the
* Compose test dispatcher thread. To avoid IllegalStateException, we ensure the removal
* happens on the main thread.
*
* @param observer The [LifecycleEventObserver] to remove.
*/
private fun Lifecycle.removeObserverOnMainThread(observer: LifecycleEventObserver) {
if (Looper.myLooper() == Looper.getMainLooper()) {
removeObserver(observer)
} else {
Handler(Looper.getMainLooper()).post {
removeObserver(observer)
}
}
}
Loading