1
votes

I am working on the android Bluetooth chat project from the developer site and i am trying to use Kotlin instead of java. i am new to Kotlin and i am just having some confusion about the "right" way to use my init block and lateinit keyword along with my companion objects. in the code that i am posting i do not have a companion object but i am wondering if i should. so far i mainly just use a companion object as a way to sort of imitate java's static class members, or to sometimes contain class constants. as for my init block i am basically using for a constructor. That is other that the assignment of members passed in through the actual constructor defined in the class declaration. As for lateinit, i am using that to declare members that i don't want to immediately initialize but also don't want to make nullable. Please let me know if this is correct usage or thing's for me to change if it is not. Here is my code:

    inner class AcceptThread(val secure:Boolean) : Thread(){
    lateinit var mmServerSocket:BluetoothServerSocket
    lateinit var mSocketType:String

    init {
        var tmp:BluetoothServerSocket? = null
        mSocketType = if (secure) "Secure" else "Insecure"

        try {
            if (secure){
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_SECURE)
            } else{
                tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, UUID_INSECURE)
            }
        }catch (ioe:IOException){
            Log.e(TAG, "Socket Type: $mSocketType listen() failed", ioe)
        }
        mmServerSocket = tmp!!
        mState = STATE_LISTEN
    }
}
2

2 Answers

3
votes

You don't need lateinit here considering you're initialising your variables in the constructor. If you would for example initialise the variables in a lifecycle method like onCreate(), then you could use a lateinit var.

Also, I think you could refactor your init block to eliminate the tmp variable:

inner class AcceptThread(val secure:Boolean) : Thread() {
val mmServerSocket: BluetoothServerSocket
val mSocketType: String = if (secure) "Secure" else "Insecure"

init {
    try {
        mmServerSocket = if (secure) {
            mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_SECURE)
        } else {
            mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, UUID_INSECURE)
        }
    } catch (ioe: IOException) {
        Log.e(TAG, "Socket Type: $mSocketType listen() failed", ioe)
    }
    mState = STATE_LISTEN
}
2
votes

Please let me know if this is correct usage or thing's for me to change if it is not.

There are two things that I'll point out regarding your code.

  1. You don't need the lateinit keyword on both mmServerSocket and mSocketType because you are initializing both variables in the constructor. You would have needed it, if the variables would have been initialized after the creation.
  2. There's one case that can throw an exception. The variable tmp can be null if an IOException is thrown. In that case, when you assign tmp to mmServerSocket a KotlinNullPointerException will be thrown. You have several possibilities to fix it: you can handle a default case in the catch block, you can make mmServerSocket nullable, etc..