fun main() {
noParam({"Hello World!" }) //Hello World!
noParam{"Hello World!"} //Hello World!
}
fun noParam(out : () -> String) = println(out())
noParam 매개변수 out은 람다식 1개를 가지고 있는데, 이 람다식에 매개변수가 없으므로 main 함수에서 인자를 넣을 때, -> 기호가 사용되지 않았습니다.
그리고 이런 경우 소괄호를 생략할 수 있습니다.
fun main() {
oneParam({ a -> "Hello World! $a"}) //Hello World! OneParam
oneParam{ a -> "Hello World! $a"} //Hello World! OneParam
oneParam{ "Hello World! $it"} //Hello World! OneParam
}
fun oneParam(out : (String) -> String) {
println(out("OneParam"))
매개변수가 1개인 람다식을 표현하고자 할 경우, 화살표를 생략하고 it 으로 대체할 수 있습니다.
fun main() {
moreParam{ a, b -> "Hello World! $a $b" }
//Hello World! OneParam TwoParam
}
fun moreParam(out : (String, String) -> String) {
println(out("OneParam", "TwoParam"))
}
람다식의 매개변수가 2개 이상인 경우는 it 으로 대체할 수 없습니다.
moreParam{ _, b -> "Hello World! $b" }
//첫 번째 문자열은 사용하지 않고 생략
이름 대신 언더스코어(_)로 대체하면 됩니다.
사실 람다 시리즈는 이 부분을 위해 작성했다고 봐도 과언이 아닙니다😅 제가 오픈 소스 코드에서 이 부분이 적용된 코드를 보다가 이해가 안 되서 람다 공부를 시작했거든요🤓
fun main() {
withArgs("Arg1", "Arg2", { a, b -> "Hello World! $a $b" })
withArgs("Arg1", "Arg2") { a, b -> "Hello World! $a $b" }
//withArgs 함수 마지막 인자가 람다식인 경우, 소괄호 바깥으로 분리 가능
}
fun withArgs(a: String, b: String, out : (String, String) -> String) {
println(out(a, b))
}
람다식이 짧으면 소괄호 안에 인자를 모두 전달할 수 있지만, 길어지면 읽기가 어렵기 때문에 main 함수의 두 번째 코드처럼 람다식만 소괄호 바깥으로 뺄 수 있습니다. 바깥으로 빠진 람다식을 withArgs 함수의 처리 부분으로 오해할 수 있으니 조심하세요~!🧐
하지만 이렇게 바깥으로 빼서 간략화하려면 람다식 매개변수가 마지막 인자 위치에 있어야 한다는 규칙이 있습니다!!!
안드로이드 개발할 때, adapter 는 반드시 한 번 이상은 구현을 해야 하는 존재인데요, adapter 를 개발할 때 자연스럽게 들어가는 녀석이 클릭이벤트 처리입니다.
클릭이벤트 처리를 구현하는 방법은 정말 다양한데, 오늘 배운 람다식으로 구현된 코드를 살펴보도록 하겠습니다.
아래는 adapter 에 data와 click event 처리 부분을 람다식으로 넣는 mainActivity의 코드 부분입니다.
...
adapter.setSearchResultList(dataList) {
Toast.makeText(
this,
"빌딩이름 : ${it.buildingName}, 주소: ${it.fullAddress}, 위도/경도: ${it.locationLatLng}",
Toast.LENGTH_SHORT
).show()
startActivity(Intent(this, MapActivity::class.java).apply {
putExtra(SEARCH_RESULT_EXTRA_KEY, it)
})
}
사용자가 지역을 검색하면 주소를 recyclerview 로 보여주고 그 recyclerview 의 adapter 가 아래와 같습니다.
class SearchRvAdapter : RecyclerView.Adapter<SearchRvAdapter.SearchResultViewHolder>() {
private var searchResultList: List<SearchResultEntity> = listOf()
private lateinit var searchResultClickListener: (SearchResultEntity) -> Unit
class SearchResultViewHolder(
val binding: ItemSearchResultBinding,
val searchResultClickListener: (SearchResultEntity) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bindData(data: SearchResultEntity) = with(binding) {
tvTitle.text = data.buildingName
tvSubtitle.text = data.fullAddress
}
fun bindView(data: SearchResultEntity) {
binding.root.setOnClickListener {
searchResultClickListener(data)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchResultViewHolder {
val view =
ItemSearchResultBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SearchResultViewHolder(view, searchResultClickListener)
}
override fun onBindViewHolder(holder: SearchResultViewHolder, position: Int) {
holder.bindData(searchResultList[position])
holder.bindView(searchResultList[position])
}
override fun getItemCount(): Int = searchResultList.size
fun setSearchResultList(
searchResultList: List<SearchResultEntity>,
searchResultClickListener: (SearchResultEntity) -> Unit
) {
this.searchResultList = searchResultList
this.searchResultClickListener = searchResultClickListener
notifyDataSetChanged()
}
}
adapter 의 멤버함수 setSearchResultList를 보면 매개변수가 일반 매개변수 하나와 람다식 매개변수 하나로 구성되어 있는 것을 알 수 있고, 람다식 매개변수가 마지막에 위치하고 있습니다. 따라서 mainActivity 에서 (dataList) 는 첫 번째 인자, { Toast.makeText...} 는 두 번째 람다식 인자에 대응되는 것입니다.
{Toast.makeText...}를 보면 중간에 it이 사용된 것을 볼 수 있는데요, 이는 람다식의 매개변수가 1개라는 뜻이죠. setSearchResultList 함수를 보면 매개변수가 (SearchResultEntity) 하나라는 것을 알 수 있습니다.
인자로 들어온 람다식은 adapter class의 searchResultClickListener 에 대입됩니다.
SearchResultViewHolder 내부의 bindView 함수를 보면, 클릭 이벤트 발생시, searchResultClickListener 변수를 함수처럼 사용해서 data 를 인자로 넣어주는 것을 알 수 있습니다. 이 data 는 람다식의 매개변수 SearchResultEntity 에 들어가고 결과적으로, 클릭하면 data에 따른 toast 메세지를 띄우게 되는 것이죠.
지금까지 람다식의 매개변수를 개수에 따라서(목차1~3), 그리고 람다식 매개변수를 갖는 함수(목차4)에 대해서 살펴보았고, 추가적으로 안드로이드 어뎁터에서 클릭이벤트를 구현할 때 적용할 수 있다는 것을 예시 코드로 확인해보았습니다. 말이 조금 헷갈릴 수 있는데요.. 😅 예시 코드를 보면서 천천히 이해하시면 좋겠습니다!