2017-10-29 78 views
0

我正在从开发人员网站开发Android蓝牙聊天项目,我正在尝试使用Kotlin而不是java。我是Kotlin的新手,我只是对使用init块和lateinit关键字以及我的伴侣对象的“正确”方式感到困惑。在我张贴的代码中,我没有伴侣对象,但我想知道我是否应该。到目前为止,我主要只是使用伴侣对象来模仿java的静态类成员,或者有时包含类常量。至于我的init块我基本上用于构造函数。除此之外,通过类声明中定义的实际构造函数传递成员的赋值。至于lateinit,我使用它来声明我不想立即初始化的成员,但也不希望为空。请让我知道,如果这是正确的用法或事情的改变,如果它不是。这里是我的代码:何时使用lateinit,init块和companion对象。 Kotlin

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 
    } 
} 

回答

3

你不需要lateinit这里考虑你初始化的变量中构造函数。例如,如果您想在像onCreate()这样的生命周期方法中初始化变量,那么您可以使用lateinit var

另外,我觉得你可以重构你的初始化块,以消除TMP变量:

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 
} 
+0

我与这个具有唯一的问题是,我无法使用瓦尔的mmServerSocket。我收到一条消息,说明属性必须初始化或抽象。那么不要使用lateinit?只要使它成为一个可空的var?你会建议什么? –

+0

所以很明显,使用try-catch块你不能使用val,考虑到try-catch意味着你不能保证获得一个有效的变量值,这种做法有意义。所以我认为这里最好的做法是使用可空的var。 – ItWillDo

+0

好的谢谢你的帮助。我做了这些改变,一切工作都很顺利。 –

2

请让我知道,如果这是正确的用法或一件事情是我 变化,如果事实并非如此。

有两件事我会指出你的代码。

  1. ,因为你是初始化在构造函数中两个变量不需要在两个mmServerSocketmSocketTypelateinit关键字。如果变量在创建之后被初始化,您将需要它。
  2. 有一种情况可能会引发异常。如果引发IOException,变量tmp可以为空。在这种情况下,当您将tmp指定为mmServerSocket时,将会抛出KotlinNullPointerException。 您有几种可能性来解决它:你可以处理在catch块默认情况下,可以使mmServerSocket空,等等。