" Park 기술 블로그 "
# 카테고리
# 도구
[Android 안드로이드] CustomView에서 @JvmOverloads
2021-08-14 19:03:02

 오늘은 Kotlin으로 CustomView를 만들 때 사용하는 @JvmOverloads에 대해서 적어두려 한다.

View는 기본적으로 3개의 생성자를 갖는다.

  1. View(Context context)
  2. View(Context context, AttributeSet attrs)
  3. View(Context context, AttributeSet attrs, int defStyle)

 1번은 소스코드에서 해당 View를 생성하고 사용할 때 호출되는 생성자고 2번과 3번 생성자는 XML에서부터 만들어진 View들 호출하는 생성자다. 그러나 내부적으로 잘 보면 2번 생성자에서 3번 생성자를 호출하고 있다. 그러면 3번 생성자는 왜 필요한가? 라는 의문이 든다. 3번 생성자는 해당 View를 상속받아 확장할 때 필요하다. 2번 생성자에서 3번 생성자를 호출할 때 3번 째 인자인 defStyle 값을 기본값으로 지정해서 호출하는데, 만약 상속받아 확장한 View에서 기본값  스타일을 사용하지 않고 다른 Style을 사용하고 싶을 경우 3번 생성자를 변경하면 된다.

 

@JvmOverloads는 위와 같은 3개의 생성자를 한개로 축약할 수 있는 장점이 있다.

class ClearEditText @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : EditText(context, attrs, defStyleAttr) { ... }

 위의 소스만 보면 생성자 3개를 직접 쓰지 않아도 되니까 깔끔해보이지만 문제가 되는 부분이 있다. @JvmOverloads는 View의 생성자 중 마지막 3번 생성자를 호출한다. 그러면 2번 생성자에서 3번 생성자를 호출할 때 3번 생성자의 int defStyle 값은 확장할 View의 기본 Style로 전달되는 것이 아니라 @JvmOverloads 생성자에 있는 기본값으로 대체된다.

 

 그러면 확장하려는 View의 2번 생성자 내부 소스를 확인해서 3번 생성자로 전달하고 있는 기본 Style 값을 @JvmOverloads의 defStyleAttr의 기본값으로 지정하면 되지 않는가? 라는 의문이 든다. 그렇게 되면 의도한대로 완벽하게 작동할 수 있다. 하지만 한가지 문제가 또 생긴다. 바로 버전이 변경되었을 경우다. 예를 들어 상속하려는 View가 버전업으로 인해 View의 2번 생성자에서 3번 생성자로 전달하는 Style 기본값이 변경된다면 휴대폰 별로 다른 Style이 보여질 것이다. 쉽게말해, @JvmOverloads의 defStyleAttr 기본값을 하드코딩 했기 때문에 발생하는 이슈다. 그래서 TextView, EditView 등등 CustomeView를 사용할 때 예기치 않은 Style 문제가 발생하는 경우 @JvmOVerloads를 사용하지 않는 것이 하나의 방법인 것 같다.

0
# 댓글 + 새 댓글 작성
# 새 댓글 작성
댓글 암호는 댓글 삭제 시 필요합니다.
# 님에게 답변 작성
대댓글 암호는 댓글 삭제 시 필요합니다.
# 님의 댓글 삭제
댓글 작성 시 입력했던 암호를 입력해주세요.
아직 댓글이 없습니다