Kotlin / kotlinx.coroutines

Library support for Kotlin coroutines
Apache License 2.0
13.09k stars 1.85k forks source link

java.lang.ClassCastException: kotlin.Result$Failure cannot be cast to kotlin.Result #2654

Closed Dark-Existed closed 3 years ago

Dark-Existed commented 3 years ago

hi, I have the similar issue to #1035

the following is my log

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-3
    Process: com.de.signcloud, PID: 8803
    java.lang.ClassCastException: kotlin.Result$Failure cannot be cast to kotlin.Result
        at com.de.signcloud.ui.signinsignup.SignInFragment$setUpObserver$2.onChanged(SignInFragment.kt:73)
        at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
        at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
        at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
        at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
        at androidx.lifecycle.Transformations$2$1.onChanged(Transformations.java:155)
        at androidx.lifecycle.MediatorLiveData$Source.onChanged(MediatorLiveData.java:152)
        at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
        at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
        at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
        at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
        at androidx.lifecycle.LiveDataScopeImpl$emit$2.invokeSuspend(CoroutineLiveData.kt:99)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

My code is folling

    private fun setUpObserver() {
        viewModel.signInWithPasswordLiveData.observe(viewLifecycleOwner, { signInResponse ->
            Log.d("SignInFragment", "???")
        })
    }
    private val signInWithPasswordEvent = MutableLiveData<SignInEvent.SignInWithPassword>()

    val signInWithPasswordLiveData = Transformations.switchMap(signInWithPasswordEvent) {
        userRepository.signInWithPassword(it.phone, it.password)
    }

    fun signInWithPassword(event: SignInEvent.SignInWithPassword) {
        signInWithPasswordEvent.value = event
    }
    fun signInWithPassword(phone: String, password: String) = liveData(Dispatchers.IO) {
        val result = try {
            Log.d("UserRepository", "Log In With Password")
            val signInResponse: SignInResponse =
                SignCloudNetwork.signInWithPassword(phone, password)
            if (signInResponse.code == 200) {
                updateUserInfo(signInResponse)
                Result.success(signInResponse)
            } else {
                Result.failure(RuntimeException("sign in response status is ${signInResponse.code}"))
            }
        } catch (e: Exception) {
            Result.failure(e)
        }
        emit(result)
    }

build.gradle

buildscript {
    ext {
        kotlin_version = '1.4.32'
        compose_version = '1.0.0-beta04'
        coroutines_version = '1.4.3'
        navigation_version = '2.3.5'
        retrofit_version = '2.9.0'
        lifecycle_version = '2.3.1'
        datastore_version = '1.0.0-alpha08'
        accompanist_version = '0.7.1'
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.0-alpha14'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.de.signcloud"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.3.0-rc01'
    implementation 'com.google.android.material:material:1.3.0'

    implementation "androidx.activity:activity-ktx:1.3.0-alpha06"
    implementation 'androidx.activity:activity-compose:1.3.0-alpha06'

    implementation "androidx.fragment:fragment-ktx:1.3.2"

    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.ui:ui-util:$compose_version"
    implementation "androidx.compose.ui:ui-tooling:$compose_version"
    implementation "androidx.compose.runtime:runtime:$compose_version"
    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.material:material-icons-extended:$compose_version"

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"

    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

    implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
    implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
    implementation "androidx.navigation:navigation-compose:1.0.0-alpha10"

    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
    implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"

    implementation "androidx.datastore:datastore-preferences:$datastore_version"

    implementation "com.google.accompanist:accompanist-coil:$accompanist_version"
    implementation "com.google.accompanist:accompanist-insets:$accompanist_version"

    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test:runner:1.3.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

So is any I can do to solve this problem?

Dark-Existed commented 3 years ago

I implemented Result myself, and solve this problem

sealed class Result<T> {
    class Success<T>(val value: T) : Result<T>()
    class Failure<T>(val error: Throwable) : Result<T>()
}

inline fun <R, T> Result<T>.fold(
    onSuccess: (value: T) -> R,
    onFailure: (exception: Throwable) -> R
): R = when (this) {
    is Result.Success -> onSuccess(value)
    is Result.Failure -> onFailure(error)
}

val <T> Result<T>.isSuccess: Boolean
    get() = when (this) {
        is Result.Success -> true
        else -> false
    }

val <T> Result<T>.isFailure: Boolean
    get() = when (this) {
        is Result.Failure -> true
        else -> false
    }

fun <T> Result<T>.getOrNull(): T? =
    when (this) {
        is Result.Success -> this.value
        else -> null
    }
marlonlom commented 3 years ago

@Dark-Existed Why a custom result for fixing the issue for the classcastexception? how can i use the custom class in this scenario? Could you explain more about the cutom result and the usage in the issue?

Dark-Existed commented 3 years ago

@Dark-Existed Why a custom result for fixing the issue for the classcastexception? how can i use the custom class in this scenario? Could you explain more about the cutom result and the usage in the issue?

You can see some similar here example1 example2

It`s a Kotlin bug, it may fixed in 1.5.+