Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I Got rarely happens Can't access ViewModels from onDestroy

I got an error like this after launch the app, and that very rarely happens.

Here my complete Java stack trace associated:

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)

Here my code, but It's very weird because I'm not set on 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)
    }
}

I try to run again on Android studio, and everything is working normally.

I want to know why can happening and how solve it?

like image 667
newbie Avatar asked Oct 24 '25 19:10

newbie


1 Answers

Looking into the Android source code, it checks if the support FragmentManager is destroyed when trying to get a ViewModel.

Calling

ViewModelProviders.of(this).get(ListModel::class.java)

will get to

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

Which will throw the exception if the FragmentManager is destroyed. Take care when the Runnable code executes with respect to the app lifecycle.

To solve this, you can:

  1. check for getSupportFragmentManager().isDestroyed() before using the ViewModel
  2. surround with try catch and ignore if does not affect your normal flow
like image 77
pumnao Avatar answered Oct 26 '25 10:10

pumnao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!