I want to implement an AnimatedContent in Compose that shows some data from an api that can return null values. When i used ViewFlipper (in Android Views Xml), i could implememnt a code that reads the state flow from a viewmodel and by observing the flow i could change the view type and pass the data. When using animated conetnt in compose with val nowplaying by viewModel. uiNowPlaying. collectAsStateWithLifecycle()
as its state, when the response is a Success and it passes the data, it crashes in the AnimatedContent Line due to a nullable item (PreviewUrl in this case) in the data class of the data (which is expected behaviour, the null):
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
at andr.mobile.mustats.domain.model.Track.hashCode(AccessToken.kt:0)
at andr.mobile.mustats.domain.model.NowPlaying.hashCode(AccessToken.kt:0)
at andr.mobile.mustats.utility.NowPlayingCustomUiState$Success.hashCode(UiStates.kt:0)
at java.util.HashMap.hash(HashMap.java:338)
at java.util.HashMap.containsKey(HashMap.java:595)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:737)
at androidx.compose.animation.AnimatedContentKt.AnimatedContent(AnimatedContent.kt:142)รง
at andr.mobile.mustats.ui.home.HomeScreenKt$HomeScreen$7$2$2.invoke(HomeScreen.kt:210)
at andr.mobile.mustats.ui.home.HomeScreenKt$HomeScreen$7$2$2.invoke(HomeScreen.kt:209)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke
......
This is my Data Class
@Parcelize
data class Track (
@SerializedName("album") var album: AlbumSimple ,
@SerializedName("artists") var artists : ArrayList<ArtistSimple>,
@SerializedName("available_markets") var availableMarkets : ArrayList<String> ,
@SerializedName("disc_number") var discNumber : Int ,
@SerializedName("duration_ms") var durationMs : Int ,
@SerializedName("explicit") var explicit : Boolean ,
@SerializedName("external_ids") var externalIds: Map<String, String> ,
@SerializedName("external_urls") var externalUrls:Map<String, String> ,
@SerializedName("href") var href: String ,
@SerializedName("id") var id : String ,
@SerializedName("is_local") var isLocal : Boolean ,
@SerializedName("name") var name : String ,
@SerializedName("popularity") var popularity : Int ,
@SerializedName("preview_url") var previewUrl: String?,
@SerializedName("track_number") var trackNumber : Int ,
@SerializedName("type") var type : String,
@SerializedName("uri") var uri : String
): Parcelable
This is my ui state whic accepts any kind of Data Class as Success
sealed class NowPlayingCustomUiState<out T> {
object Loading : NowPlayingCustomUiState<Nothing>()
object NoContent : NowPlayingCustomUiState<Nothing>()
data class Success<T>(val data: T, val history: Boolean) : NowPlayingCustomUiState<T>()
data class Error(@StringRes val message: Int) : NowPlayingCustomUiState<Nothing>()
object NetworkException : NowPlayingCustomUiState<Nothing>()
}
This is what i want to implement
val nowplaying by viewModel. uiNowPlaying. collectAsStateWithLifecycle()
AnimatedContent(
modifier = Modifier,
targetState = nowplaying,
label = "users animated content"
) { state ->
when (state) {
is NowPlayingCustomUiState.Success -> PlayingInfo(state.data, state.history)
else -> {}
}
}
This is happening due to the animated content because i had no previous problemns in Xml android. Is there a workaround so that animated content accepts Dataclasses with nullables items in it?