airbnb / mavericks

Mavericks: Android on Autopilot
https://airbnb.io/mavericks/
Apache License 2.0
5.84k stars 498 forks source link

Failed to call observer method #230

Closed vee-zhang closed 5 years ago

vee-zhang commented 5 years ago

MvRxState-version:1.0.0

ViewModel:

package com.example.mvrx_test.login

import com.airbnb.mvrx.*
import com.example.mvrx_test.*
import com.example.mvrx_test.Constant.JSON_MEDIA
import com.squareup.moshi.Moshi
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import org.koin.android.ext.android.inject

data class TasksState(
    val userBean: UserBean? = null,
    val request: Async<LaiKangJunVO<UserBean>> = Uninitialized
) : MvRxState

/**
 * ViewModel实现业务逻辑
 */
class LoginVM(loginTaskState: TasksState, private val source: NetService) : MvRxViewModel<TasksState>(loginTaskState) {

    /**
     * 必须有一个initialState
     * source是数据源,可以是数据库,也可以是网络请求等(例子中是数据库)
     **/
    companion object : MvRxViewModelFactory<LoginVM, TasksState> {

        /**
         * 工厂方法,必须实现MvRxViewModelFactory接口
         * 主要用途是通过依赖注入传入一些参数来构造ViewModel
         * TasksState是MvRx帮我们构造的(通过反射)
         **/
        override fun create(viewModelContext: ViewModelContext, state: TasksState): LoginVM? {
            //注入
            val service: NetService by viewModelContext.activity.inject()
            return LoginVM(state, service)
        }
    }

    init {
        // 方便调试,State状态改变时打印出来
        logStateChanges()
    }

    fun login(mobile: String, pwd: String) = withState { it ->

        if (it.request is Loading) return@withState

        source.login(mobile, pwd).subscribeOn(Schedulers.io()).execute {
            copy(request = it, userBean = it()?.data)
        }
    }
}

My View:

package com.example.mvrx_test.login

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProviders
import com.airbnb.mvrx.BaseMvRxFragment
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.fragmentViewModel
import com.example.mvrx_test.R
import kotlinx.android.synthetic.main.fragment_login.*

class LoginFragment : BaseMvRxFragment() {

    val vm: LoginVM by fragmentViewModel()

    override fun invalidate() {
        val i = 0
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_login, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        vm.asyncSubscribe(TasksState::request, onFail = {
            val i = 0
        })

        btn_login.setOnClickListener {
            val mobile = et_account.text.toString()
            val pwd = et_pwd.text.toString()
//            vm.login(mobile, pwd)
        }
    }
}

result:

04-15 18:45:45.660 13991-13991/com.example.mvrx_test E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mvrx_test, PID: 13991
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mvrx_test/com.example.mvrx_test.MainActivity}: java.lang.RuntimeException: Failed to call observer method
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2679)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2750)
        at android.app.ActivityThread.-wrap13(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1595)
        at android.os.Handler.dispatchMessage(Handler.java:111)
        at android.os.Looper.loop(Looper.java:207)
        at android.app.ActivityThread.main(ActivityThread.java:5975)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
     Caused by: java.lang.RuntimeException: Failed to call observer method
        at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:226)
        at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
        at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
        at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36)
        at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
        at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
        at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
        at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
        at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
        at androidx.fragment.app.Fragment.performCreate(Fragment.java:2534)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:843)
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManagerImpl.java:2092)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1866)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1822)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1723)
        at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2624)
        at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2580)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2571)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:907)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1235)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1301)
        at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2620)
        at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2580)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1245)
        at android.app.Activity.performStart(Activity.java:6332)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2642)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2750) 
        at android.app.ActivityThread.-wrap13(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1595) 
        at android.os.Handler.dispatchMessage(Handler.java:111) 
        at android.os.Looper.loop(Looper.java:207) 
        at android.app.ActivityThread.main(ActivityThread.java:5975) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.airbnb.mvrx.MvRxViewModelProvider.createViewModel$mvrx_release(MvRxViewModelProvider.kt:51)
        at com.airbnb.mvrx.MvRxViewModelProvider.createViewModel$mvrx_release$default(MvRxViewModelProvider.kt:45)
        at com.airbnb.mvrx.MvRxViewModelProvider$get$factory$1.invoke(MvRxViewModelProvider.kt:33)
        at com.airbnb.mvrx.MvRxViewModelProvider$

Why???

Protino commented 5 years ago

Hey did you find out what the issue was?

idrisadetunmbi commented 4 years ago

I had this stacktrace in my app (different version though and might actually not be the same cause) and was able to resolve it through this: https://github.com/airbnb/MvRx/wiki/Integrating-MvRx-In-Your-App#configure-global-mvrx-plugins.

libliboom commented 3 years ago

Plus, It's not related to the first description, but it's important that all of the property in MvRxState has to have a default value like guidance(https://github.com/airbnb/MvRx/wiki#initial-state) to avoid Failed to call observer method.