简体   繁体   中英

Android Kotlin: check if view is not null before displaying Snackbar

I used the following code to display a snackbar when data has been loaded using retrofit .

Sometimes, I get a NullPointerException when user tries to navigate from this fragment to another one whereas the request to get data is not yet terminated:

kotlin.KotlinNullPointerException at com.test.data.ui.cars.SiteCarsFragment$getCars$1.onFailure(SiteCarsFragment.kt:279) at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$2.run(DefaultCallAdapterFactory.java:92) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:224) at android.app.ActivityThread.main(ActivityThread.java:7520) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.Z93F725A07423FE1C889F448B33D21F 46Z:539) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

It's due to the fact that view is null in that case.

How can I modify the code to be sure that the view is defined before displaying the snackbar?

// Call getCars() API
val call = App.myService.getCars(site.id!!)
call.enqueue(object : Callback<CarsResponse> {

    override fun onResponse(call: Call<CarsResponse>, response: Response<CarsResponse>) {

        Log.i(tagLabel, "getCars() - onResponse() Result = ${response.body()}")

        if (response.code() == 200) {

            if (response.body()?.data?.size == 0){
                // do stuff
            } else {
                val sb = Snackbar.make(view!!, getString(R.string.mytitle), Snackbar.LENGTH_SHORT)
                sb.view.setBackgroundColor(ContextCompat.getColor(context!!, R.color.snackbarGreen))
                sb.show()
            }

        }
    }

    override fun onFailure(call: Call<CarsResponse>, t: Throwable) {
        // do stuff
    }

})

I would try this one. I just added a null check

if(view != null){

  // Your code
  val sb = Snackbar.make(view!!, getString(R.string.mytitle), Snackbar.LENGTH_SHORT)
  sb.view.setBackgroundColor(ContextCompat.getColor(context!!, R.color.snackbarGreen))
  sb.show()
}

You should use a view referenced to your activity (as activity views will not be destroyed if one of your fragment is). If you have any instance of activity's view, pass it there.

Or you can try this:

val sb = Snackbar.make(activity!!.findViewById(android.R.id.content), getString(R.string.mytitle), Snackbar.LENGTH_SHORT)

here I have used !! but activity will not be null unless its destroyed.

Edit: Here if you use view of fragment with null check, your snackbar will not be shown if your fragment's view is destroyed by switching between fragments. So you should use a activity's view or the code above if you want it to be shown even after your fragment's view destroyed.

I would recommend you to get rid of the double-bang(!!) operator and use the null-safety(?) operator, in the place where you are using view!! and context.!.

You should do something like this:

if(view !=null){
//TODO Snakbar code here.
}

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM