상세 컨텐츠

본문 제목

[Kotlin, Android] let, with, run, apply, also

안드로이드/basic

by 개발혱 2021. 5. 9. 01:12

본문

각 함수에 대해서 정의를 내려보고 안드로이드에서는 어떻게 쓰고 있는지 보겠습니다.

 

Scope Functions

객체 컨테스트 내에서 코드 블록을 실행하는 구조입니다. 제공된 람다 식을 사용하여 개체에서 함수를 호출합니다.

이 범위에서 이름없이 객체에 액세스 할 수 있습니다.

 

1. let

객체가 존재하는 상태에서 객체의 상태를 변경시킬 때 사용합니다.

data class Car(var name : String)

fun main() {
    var car = Car("ray")
    car.let{
        it.name = "morning"
    }
     println(car)    
}

//Car(name=morning)

T?.let {} 형태는 non-null 형태로 쓸 수 있는데 null인 경우엔 어떻게 해줘야할지 고민이 되었는데 elvis operator ?: 를 사용해서 기본값 지정해줄 수 있습니다.

let을 java로 쉽게 설명하면 삼항 연산자라고 생각하면 어떨까? 기존 삼항연산자의 경우엔, (조건문)? turue : false 형태인데 let형태를 삼항연산자로 생각하면 좀 더 쉽게 생각하는게 가능 할 것 같다. 

fun main() {
    var car : Car? = Car("ray")
    println(car?.let { it.name } ?: "Car does not exist.")
    
    var car2 : Car? = null
    println(car2?.let { it.name } ?: "Car does not exist.")
}

//ray
//Car does not exist.

2. with

객체 상태를 this 형태로 호출되어 let과 다르게 속성값에 it.name 없이 바로 name으로 변경이 가능합니다.

fun main() {
    var car : Car = Car("ray")
    
	with(car){
    	println(this)
        println(name)
        name = "morning"
        println(name)
    }
}

//Car(name=ray)
//ray
//morning

메서드를 실행할 때도 쓰기도 합니다.

 with(viewModel) {
   if (isFiltered()) {
     clearGrowZoneNumber()
   } else {
   	setGrowZoneNumber(9)
   }
 }

3. run

with와 유사하지만 run경우엔 null체크 가능해서 with보다 활용도가 높습니다.

recyclerView.run {
    layoutManager = LinearLayoutManager(this@MainActivity)
    adapter = this@MainActivity.adapter
}

4. apply

run과 유사하지만 return 값 받지 않고 자기 자신 호출합니다. it타입지정 없이 바로 그 함수에 메소드를 접근해서 사용하는게 장점인 듯 합니다.

 

캘린더에 날짜를 지정하는 경우

  private val cal = Calendar.getInstance().apply {
        set(YEAR, 1998)
        set(MONTH, SEPTEMBER)
        set(DAY_OF_MONTH, 4)
    }

hashmap에 데이터를 추가하는 경우,

 val header= HashMap<String, Any>().apply {
     put("api_version", DevicePref.api_version)
}

5. also

값을 변경하지 않고 자기 자신을 리턴합니다.

 

아래엔 리사이클러뷰에서 리스트 형식을 그리드 방식으로 적용할 때 also 형태로 적용해 본 것입니다.

  binding.gallery.also { view ->
        view.layoutManager = GridLayoutManager(this, 3)
        view.adapter = galleryAdapter
  }

 

앱 설정화면 호출시에 .also를 넣어서 실행 하도록 한 예제입니다.

startActivity를 화면 인텐트로 준 화면으로 이동하게 됩니다.

 Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:$packageName")).apply {
            addCategory(Intent.CATEGORY_DEFAULT)
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
 }.also { intent ->
        startActivity(intent)
 }

 

객체에 상태값을 변경해줍니다.

 @Test fun testGetGardenPlantings() = runBlocking {
        val gardenPlanting2 = GardenPlanting(
            testPlants[1].plantId,
            testCalendar,
            testCalendar
        ).also { it.gardenPlantingId = 2 }
        gardenPlantingDao.insertGardenPlanting(gardenPlanting2)
        assertThat(gardenPlantingDao.getGardenPlantings().first().size, equalTo(2))
}

 

Closing Thought

안드로이드에 코틀린 적용한 예제 내가 처음일 줄 알았는데 다른 사람도 정리해 놓은게 있었다.

그래도 생각만으로 멈추는게 아니라 직접 실행해보니 다음엔 문법 헷갈릴 때 내가 적은 내용보면서 적용해봐야겠다.

 

참고자료

- kotlinlang.org/docs/scope-functions.htm

- blog.yena.io/studynote/2020/04/15/Kotlin-Scope-Functions.html

- [Android Sunflower 예제](github.com/android/sunflower)

 

android/sunflower

A gardening app illustrating Android development best practices with Android Jetpack. - android/sunflower

github.com

- black-jin0427.tistory.com/169

'안드로이드 > basic' 카테고리의 다른 글

GC  (0) 2022.06.15
JVM 메모리 구조  (0) 2022.06.15
동영상 보며 코루틴동영상 보며 코루틴 요약하기  (0) 2021.03.28
Kotlin Null 체크(? / ?: / !!)  (0) 2021.03.05
Android GPS Tutorial  (0) 2021.02.20

관련글 더보기