java.lang.IllegalStateException: You must either set a text or a view

Viewed 8363

I'm new to android and I keep getting this error while clicking on a button which process database requests. I don't know what's going on because everything was working yesterday and I didn't do any changes at all.

The errorlog:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 7510
java.lang.IllegalStateException: You must either set a text or a view
    at com.android.internal.util.Preconditions.checkState(Preconditions.java:173)
    at android.widget.Toast.show(Toast.java:188)
    at com.example.myapplication.LoginActivity$userLogin$stringRequest$3.onErrorResponse(LoginActivity.kt:106)
    at com.android.volley.Request.deliverError(Request.java:617)
    at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:104)
    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)

And the code errorlog refers to:

private fun userLogin() {
        val email: String = emailText.text.toString().trim()
        val password: String = passwordText.text.toString().trim()

        val stringRequest = object : StringRequest(
                Method.POST, URL_LOGIN,
                Response.Listener<String> { response ->
                    try {
                        val obj = JSONObject(response)
                        if (!obj.getBoolean("error")) {
                            SharedPrefManager.getInstance(applicationContext)
                                    ?.userLogin(
                                            obj.getInt("id"),
                                            obj.getString("email"))
                            Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                        }else{
                            Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                        }
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                },
                Response.ErrorListener { volleyError -> Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show() }) {
            @Throws(AuthFailureError::class)
            override fun getParams(): Map<String, String> {
                val params = HashMap<String, String>()
                params.put("email", email)
                params.put("password", password)
                return params
            }
        }

Code which is calling this function:

 override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.login_layout)

    buttonLogin.setOnClickListener {
        userLogin()
        this.finish()
    }
}

Honestly, I have no idea what this error means, if I need to provide more code please let me know.

4 Answers

in android 11(API level 30) Compatibility.isChangeEnabled(CHANGE_TEXT_TOASTS_IN_THE_SYSTEM) will return true in Toast class show() method, for android 11 as mention in android developer site

for now if you want to skip this exception don't pass null in message parameter of Toast Toast.makeText(applicationContext, obj.getString("message"),Toast.LENGTH_LONG).show() here your obj.getString("message") getting null for certain cases so you check null then show Toast like following

if(obj!=null && obj.getString("message")!=null){
Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()
}else//static message

like this we can prevent exception

private fun userLogin() {
        val email: String = emailText.text.toString().trim()
        val password: String = passwordText.text.toString().trim()

        val stringRequest = object : StringRequest(
                Method.POST, URL_LOGIN,
                Response.Listener<String> { response ->
                    try {
                        val obj = JSONObject(response)
                        if (!obj.getBoolean("error")) {
                            SharedPrefManager.getInstance(applicationContext)
                                    ?.userLogin(
                                            obj.getInt("id"),
                                            obj.getString("email"))
                            Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                        }else{
                            Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                        }
                           this.finish()
                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                },
                Response.ErrorListener { volleyError -> Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show() }) {
            @Throws(AuthFailureError::class)
            override fun getParams(): Map<String, String> {
                val params = HashMap<String, String>()
                params.put("email", email)
                params.put("password", password)
                return params
            }
        }


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.login_layout)

    buttonLogin.setOnClickListener {
        userLogin()
       
    }
}

I changed the userLogin() method to this:

private fun userLogin() {
val email: String = emailText.text.toString().trim()
val password: String = passwordText.text.toString().trim()

val stringRequest = object : StringRequest(
        Method.POST, URL_LOGIN,
        Response.Listener<String> { response ->
            try {
                val obj = JSONObject(response)
                if (!obj.getBoolean("error")) {
                    SharedPrefManager.getInstance(applicationContext)
                            ?.userLogin(
                                    obj.getInt("id"),
                                    obj.getString("email"))
                    Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                }else{
                    Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG).show()

                }
            } catch (e: JSONException) {
                e.printStackTrace()
            }
        },
        Response.ErrorListener { volleyError->
            run {
                Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG).show()
                Log.d("volleyError", "${volleyError.message}")
            }
        }) {

    @Throws(AuthFailureError::class)
    override fun getParams(): Map<String, String> {
        val params = HashMap<String, String>()
        params.put("email", email)
        params.put("password", password)
        return params
    }
}
VolleySingleton.instance?.addToRequestQueue(stringRequest)

}

And everything seems to work, I have no idea why but it works.

You must check for Toast message from before to be closed

    Toast mToast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);

    // cancel previous toast and display correct answer toast
    try {
        if (mToast.getView().isShown()) {
            mToast.cancel();
        }
        // cancel same toast only on Android P and above, to avoid IllegalStateException on addView
        if (Build.VERSION.SDK_INT >= 28 && mToast.getView().isShown()) {
            mToast.cancel();
        }
        mToast.show();
    } catch (Exception e) {
        e.printStackTrace();
        mToast.show();//This line will show toast if previous toast is null
    }

You this function in a global class , And use it for Toasting in anywhere

Related