이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.
작성 시점: 2017-06-22
리스너 패턴에 사용되던 자바의 인터페이스를 코틀린의 function로 변환하는 과정을 정리해보려 한다.
interface PermissionRequestCallback {
fun onPermissionResult(resultCode: Int, list: ArrayList<String>)
}
Convert java into kotlin 변환기 사용해서 생성한 인터페이스이다. 하나의 메소드를 가지고 있으며 resultCode: Int, list: ArrayList 의 두개의 파라미터를 가지고 있다.
기존에 checkPermission은 fun checkPermission(list: ArrayList<String>, callback: PermissionRequestCallback? = null): Boolean
이런 구조였으나 인터페이스를 Function으로 교체하기 위해 callback: (Int, ArrayList<String>) -> Unit
로 교체해주었다. 두 개의 파라미터를 가지면 순서대로 해당 변수의 타입명을 적어주고, 리턴값은 없어도 되니 Unit를 사용한다. 기본값은 설정하지 않았다. (보통, 권한 요청하고 받으면 바로 작업을 실행하게 만들기 때문이다.)
기본값을 추가시키게 되면 형태는 callback: (Int, ArrayList<String>) -> Unit = {}
가 된다.
만일 파라미터가 하나일 경우 callback: Int.() -> Unit
라고 해도 무방하다.
최종적으로 수정된 checkPermission은 아래와 같다.
/**
* check and request Permission which given.
*
* @param[array] array of Permission to check
* @param[callback] callback object
* @return check result
*/
fun checkPermission(array: Array<String>, callback: (Int, ArrayList<String>) -> Unit): Boolean {
val permissionList: ArrayList<String> = ArrayList()
array.forEach { permissionList.add(it) }
return checkPermission(permissionList, callback)
}
기타 checkPermission, requestPermission 등도 위와 같이 수정했다.
사용할때는 비교적 간단하다. 기존에는 callback?.onPermissionResult(PERMISSION_ALREADY, list)
이런 식으로 사용했었는데, callback(PERMISSION_ALREADY, list)
로 바꿔주면 된다.
Before
class Callback : RPermission.PermissionRequestCallback {
override fun onPermissionResult(resultCode: Int, list: ArrayList<String>) {
alert(message = "Permission result -> $resultCode / Requested Permission: ${TextUtils.join(",", list)}")
}
}
btnCall.setOnClickListener {
val arrays : Array<String> = arrayOf(Manifest.permission.CALL_PHONE)
RPermission.getInstance(this).checkPermission(arrays, Callback())
}
After
btnCall.setOnClickListener {
val arrays: Array<String> = arrayOf(Manifest.permission.CALL_PHONE)
RPermission.getInstance(this).checkPermission(array = arrays, callback = { resultCode: Int, list: ArrayList<String> ->
alert(message = "Permission result -> $resultCode / Requested Permission: ${TextUtils.join(",", list)}")
})
}
코드도 더 짧아졌고, 무엇보다 class를 선언하지 않아도 된다는게 아주 좋아졌다.
btnCall.setOnClickListener(view -> {
String[] arrays = new String[]{Manifest.permission.CALL_PHONE};
RPermission.Companion.getInstance(this).checkPermission(arrays, (integer, strings) -> {
Utils.alert(PermissionActivity.this,
"Permission result ->" + integer + " / Requested Permission: " + TextUtils.join(",", strings));
return Unit.INSTANCE;
});
});
람다식을 사용하게 되면 코틀린과 거의 비슷하게 사용할 수 있다.
사용하지 않게 되면..
btnCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String[] arrays = new String[]{Manifest.permission.CALL_PHONE};
RPermission.Companion.getInstance(PermissionActivity.this).checkPermission(arrays, new Function2<Integer, ArrayList<String>, Unit>() {
@Override
public Unit invoke(Integer integer, ArrayList<String> strings) {
Utils.alert(PermissionActivity.this,
"Permission result ->" + integer + " / Requested Permission: " + TextUtils.join(",", strings));
return Unit.INSTANCE;
}
});
}
});
람다를 사용하지 않게 되는 경우는 제외하고, 단순히 리스너 패턴으로 사용했던 인터페이스는 function으로 갈아타는게 좀 더 가독성도 있을 뿐더러 코드가 짧아진다는 결론에 도착하였다.
이제 남은건, 다른 클래스들도 이렇게 변환하는 것이다.