我很少发生无法从 onDestroy 访问 ViewModel

new*_*bie 3 android kotlin android-architecture-components

启动应用程序后我收到了这样的错误,这种情况很少发生。

这是我完整的 Java 堆栈跟踪相关联:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.mycompany.myapp.dev, PID: 11145
              java.lang.IllegalStateException: Can't access ViewModels from onDestroy
                  at android.arch.lifecycle.HolderFragment$HolderFragmentManager.findHolderFragment(HolderFragment.java:136)
                  at android.arch.lifecycle.HolderFragment$HolderFragmentManager.holderFragmentFor(HolderFragment.java:155)
                  at android.arch.lifecycle.HolderFragment.holderFragmentFor(HolderFragment.java:81)
                  at android.arch.lifecycle.ViewModelStores.of(ViewModelStores.java:42)
                  at android.arch.lifecycle.ViewModelProviders.of(ViewModelProviders.java:88)
                  at com.mycompany.myapp.ui.splash.SplashActivity$viewModel$2.invoke(SplashActivity.kt:47)
                  at com.mycompany.myapp.ui.splash.SplashActivity$viewModel$2.invoke(SplashActivity.kt:40)
                  at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130)
                  at com.mycompany.myapp.ui.splash.SplashActivity.getViewModel(SplashActivity.kt:0)
                  at com.mycompany.myapp.ui.splash.SplashActivity$onResume$1.run(SplashActivity.kt:62)
                  at android.os.Handler.handleCallback(Handler.java:815)
                  at android.os.Handler.dispatchMessage(Handler.java:104)
                  at android.os.Looper.loop(Looper.java:207)
                  at android.app.ActivityThread.main(ActivityThread.java:5805)
                  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)
Run Code Online (Sandbox Code Playgroud)

这是我的代码,但很奇怪,因为我没有设置 onDestroy()

class SplashActivity : AppCompatActivity(){
    GoogleApiClient.OnConnectionFailedListener {
    val context = this

    val viewModel by lazy {
        ViewModelProviders.of(this).get(ListModel::class.java)
    }

    override fun onResume() {
        super.onResume()

        Handler().postDelayed(object: Runnable{
            override fun run() {
                val testConnection = viewModel?.testConnectionLiveData()
                viewModel?.testConnection()

                testConnection?.observe(context, Observer<TestConnectionData> { tc ->
                    tc?.let {
                        if (tc.status == "FAILED") {
                            var builder: AlertDialog = AlertDialog.Builder(context).create()
                            builder.setTitle("Failed Connect To Server")
                            builder.setMessage("The app cannot reach on the server. Make sure your device connect the internet and try again!")
                            builder.setButton(AlertDialog.BUTTON_POSITIVE, "OK", object : DialogInterface.OnClickListener {
                                override fun onClick(dialog: DialogInterface?, which: Int) {
                                    var i = Intent(context, LoginActivity::class.java)
                                    startActivity(i)
                                }
                            })

builder.setIcon(android.R.drawable.ic_dialog_alert)
                        builder.setCancelable(false)
                        builder.setCanceledOnTouchOutside(false)
                        builder.show()
                        } else if(tc.status == "SUCCESS"){
                            var i = Intent(context, LoginActivity::class.java)
                            startActivity(i)
                        }
                    }
                })
            }
        }, 5000)
    }

    @SuppressLint("MissingPermission")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN)
        setContentView(R.layout.activity_splash)
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试在 Android Studio 上再次运行,一切正常。

我想知道为什么会发生以及如何解决?

pum*_*nao 6

查看 Android 源代码,它会在尝试获取 ViewModel 时检查支持 FragmentManager 是否被破坏。

打电话

ViewModelProviders.of(this).get(ListModel::class.java)
Run Code Online (Sandbox Code Playgroud)

将到达

private static HolderFragment findHolderFragment(FragmentManager manager) {
    if (manager.isDestroyed()) {
        throw new IllegalStateException("Can't access ViewModels from onDestroy");
    }
Run Code Online (Sandbox Code Playgroud)

如果 FragmentManager 被销毁,这将引发异常。Runnable 代码在应用程序生命周期方面的执行时要小心。

要解决此问题,您可以:

  1. 在使用 ViewModel 之前检查 getSupportFragmentManager().isDestroyed()
  2. 用 try catch 包围并忽略如果不影响您的正常流程