Changing Button Color on MainActivity via RunOnUIThread Crashes

65 Views Asked by At

I am getting a

kotlin.UninitializedPropertyAccessException: lateinit property BTNStatus05 has not been initialized

When I try to set a ButtonColor. The idea is to change butttoncolor etc on a button, based on reply via a TCPsocket. In my

My Main Activity Simplified:

class MainActivity() : AppCompatActivity(), Parcelable {
    constructor(parcel: Parcel) : this() {

    }
    private var fgm: SygicNaviFragment? = null
    private var uiInitialized = false
    private val TAG = "MainActivity"
    private lateinit var socketHandler: SocketHandler
    private lateinit var handlerThread: HandlerThread
    lateinit var BTNStatus05 : Button


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (PermissionsUtils.requestStartupPermissions(this) == PackageManager.PERMISSION_GRANTED) {
            checkSygicResources()
            Log.i(TAG, "onCreate: Sygic Resources checked")
        }
        //this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN)

        window.decorView.apply {
           systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
        }
        setContentView(R.layout.activity_main)

        handlerThread = HandlerThread("").apply {
            start()
            socketHandler = SocketHandler(looper)


            socketHandler?.obtainMessage()?.also { msg ->
                msg.what = 0
                msg.obj = "INIT"
                msg.arg1 = 0
                socketHandler?.sendMessage(msg)}

        }
       
        // set on-click listener
        BTNStatus05= findViewById(R.id.statusbutton05) as Button
        Log.d(TAG, "BTN05" + BTNStatus05)
            //BTNStatus05.setBackgroundColor(Color.YELLOW)
            //BTNStatus05.setEnabled(false)
        BTNStatus05.setOnClickListener {
            socketHandler?.obtainMessage()?.also { msg ->
                msg.what = 1
                msg.obj = "btnpress"
                msg.arg1 = 5
                socketHandler?.sendMessage(msg)
            }
            Toast.makeText(this@MainActivity, "Status05 Clicked.", Toast.LENGTH_SHORT).show()
        }
            
    fun Test() {
           Log.d(TAG, "DATA on Mainthread? " + Thread.currentThread().name)
           Log.d(TAG, "Stop: We Got a button:")
           BTNStatus05.setBackgroundColor(Color.YELLOW)
           BTNStatus05.setEnabled(false)
    }

    override fun onCreateDialog(id: Int): Dialog {
        return fgm?.onCreateDialog(id) ?: return super.onCreateDialog(id)
    }

    override fun onPrepareDialog(id: Int, dialog: Dialog) {
        super.onPrepareDialog(id, dialog)
        fgm?.onPrepareDialog(id, dialog)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        fgm!!.onNewIntent(intent)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        fgm?.onActivityResult(requestCode, resultCode, data)
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        return fgm?.onKeyDown(keyCode, event) ?: return super.onKeyDown(keyCode, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        return fgm?.onKeyUp(keyCode, event) ?: return super.onKeyUp(keyCode, event)
    }



    override fun writeToParcel(parcel: Parcel, flags: Int) {

    }


       override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<MainActivity> {
        override fun createFromParcel(parcel: Parcel): MainActivity {
            return MainActivity(parcel)
        }

        override fun newArray(size: Int): Array<MainActivity?> {
            return arrayOfNulls(size)
        }
    }


   inner class MainHandler(mainlooper: Looper) : Handler(mainlooper) {
        private val TAG = "MainActivity"
        val mainA = MainActivity()
       val mapper = jacksonObjectMapper()
        override fun handleMessage(msg: Message) {
            Log.d(TAG, "Handle")
            super.handleMessage(msg)
            val jsonstr = msg?.obj as String
            val jsontree = mapper.readTree(jsonstr)
            val type = jsontree.get("type").asText()
            Log.d(TAG, "Mainhandler: jsonstr - " + jsonstr)
            Log.d(TAG, "MainHandler:Json type -  " + type )
            when(type) {
                           "button" -> {
                    Log.d(TAG, "We got button update: " + type)

                        MainActivity().runOnUiThread(Runnable {
                        BTNStatus05.setBackgroundColor(Color.YELLOW) })
                        //BTNStatus05.setBackgroundColor(Color.YELLOW)

                }
                else -> Log.d(TAG, "unknown what " + type)
            }
                   }
    }
}

I tried:

when(type) {
                           "button" -> {
                    Log.d(TAG, "We got button update: " + type)

                        MainActivity().runOnUiThread(Runnable {
                        BTNStatus05.setBackgroundColor(Color.YELLOW) })
                        //BTNStatus05.setBackgroundColor(Color.YELLOW)

                }
                else -> Log.d(TAG, "unknown what " + type)


And also just did a call to test() instead... Any ideas?

1

There are 1 best solutions below

0
Khush Parmar On
kotlin.UninitializedPropertyAccessException: lateinit property BTNStatus05 has not been initialized

This exception asks that your code is accessing property which is declared as lateinit and has not been initialized. So, when you are declaring BTNStatus05 as lateinit you must need to initialize it prior of it's access by any other line on code. In your case when the MainHandler calls BTNStatus05.setBackgroundColor(Color.YELLOW) the BTNStatus05 is not initialized.

To resolve this just move this line of initialization of the button BTNStatus05= findViewById(R.id.statusbutton05) as Button inside first line of onCreate method like below.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    BTNStatus05= findViewById(R.id.statusbutton05)
    // Other code
}

This will initialize your button prior of the access and it will not throw the same exception.