버튼을 눌러 주사위를 굴려 값을 얻는 예제를 실행하기 위해 다음과 같이 코드를 작성하였다.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val rollButton: Button = findViewById(R.id.roll_button)
        rollButton.setOnClickListener{
            rollDice()
        }

        diceImage = findViewById(R.id.dice_image)
    }

    private fun rollDice() {

        val randomInt = Random().nextInt(6) + 1

        val drawableResource = when (randomInt){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }
        val diceImage: ImageView = findViewById(R.id.dice_image)
        diceImage.setImageResource(drawableResource)
    }
}

26번째 줄을 보면 함수가 실행 될 때마다 diceImage 변수를 생성하여 findViewById 함수를 이용하여 초기화를 하기 때문에 비효율적이다.

val diceImage: ImageView = findViewById(R.id.dice_image)

findViewById 함수는 Id의 트리를 모두 탐색하기 때문에 여러번 호출하는 것은 앱의 실행 시간에 영향을 끼칠 수 있다.

 

따라서 다음과 같이 코드를 수정하였다.

class MainActivity : AppCompatActivity() {

    val diceImage: ImageView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val rollButton: Button = findViewById(R.id.roll_button)
        rollButton.setOnClickListener{
            rollDice()
        }

        diceImage = findViewById(R.id.dice_image)
    }

    private fun rollDice() {

        val randomInt = Random().nextInt(6) + 1

        val drawableResource = when (randomInt){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }
        val diceImage: ImageView = findViewById(R.id.dice_image)
        diceImage.setImageResource(drawableResource)
    }
}

3번째 줄에 변수로 diceImage를 생성, null로 초기화해준다.

val diceImage: ImageView? = null

그러나 이 코드 역시 변수를 사용하기 위해서 null 체크를 해줘야 하는 번거로움이 남는다.

이를 다음과 같이 lateinit을 사용하면 나중에 변수의 값을 초기화 해줄 수 있다.

lateinit val diceImage: ImageView

하지만 이 코드를 실행하려고 하면 'lateinit' modifier is allowed only on mutable properties 라는 에러가 발생하는데

이는 lateinit 은 immutable(불변) 타입인 val에 사용할 수 없기 때문이다.

따라서 val 변수을 mutable(가변) 타입인 var으로 바꿔주면된다.

lateinit var diceImage: ImageView
class MainActivity : AppCompatActivity() {

    lateinit var diceImage: ImageView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val rollButton: Button = findViewById(R.id.roll_button)
        rollButton.setOnClickListener{
            rollDice()
        }

        diceImage = findViewById(R.id.dice_image)
    }

    private fun rollDice() {

        val randomInt = Random().nextInt(6) + 1

        val drawableResource = when (randomInt){
            1 -> R.drawable.dice_1
            2 -> R.drawable.dice_2
            3 -> R.drawable.dice_3
            4 -> R.drawable.dice_4
            5 -> R.drawable.dice_5
            else -> R.drawable.dice_6
        }

        diceImage.setImageResource(drawableResource)
    }
}

val 변수의 초기화를 나중에 하고 싶다면 'by lazy'를 사용하면 되는데 val 변수이기 때문에 나중에 한번 초기화한 이후엔 바꿀 수 없다.

val diceImage: ImageView by lazy

 

 

결론

- findViewById 함수를 여러번 호출하는 것은 앱의 실행 시간에 영향을 끼칠 수 있다.

- lateinit val은 불가능 하며 lateinit var를 사용하거나 by lazy를 사용한다.

 

참고
 

Developing Android Apps with Kotlin

Learn the fundamentals of the Kotlin programming language from Kotlin experts at Google.

www.udacity.com

 

+ Recent posts