IOS를 사랑하는 AOS 개발자
[Android] Annotation 본문
반응형
SMALL
👼🏻 초보 안드로이드 개발자가 매번 구글링하기 싫어서 정리하는 블로그 👼🏻
안녕하세요! 🙋🏻♀️
Annotation 에 관해 작성해 보았습니다.
Annotation 이란?
- 소스 코드에 메타데이터를 추가하는 방법 중 하나.
- 해당 메타데이터는 컴파일러나 다른 도구가 소스 코드를 처리하거나 실행할 때 정보를 제공한다.
- 또한 코드를 더 간결하고 가독성있게 만들고, 런타임 동작을 변경하거나 개선하는데 도움이 된다.
Resource 관련 Annotation [[참고 사이트#1]]
메서드나 지역 변수, 필드 반환 값이 리소스 참조가 될 것으로 예상됨을 나타낸다.
@AnimatorRes
: animator 리소스 참조 (android.R.animator.
)@AnimRes
: anim 리소스 참조 (android.R.anim.
)@AnyRes
: 모든 타입의 리소스 참조 (특정 타입을 알고 있는 경우 구체적인 주석을 사용하면 됨)@ArrayRes
: 배열 타입의 리소스 참조 (android.R.array.
)@AttrRes
: attribute 리소스 참조 (android.R.attr.
)@BoolRes
: boolean 리소스 참조@ColorRes
: color 리소스 참조 (android.R.color.
)@DimenRes
: dimen 리소스 참조 (android.R.dimen.
)@DrawableRes
: drawable 리소스 참조 (android.R.attr.
)@FontRes
: font 리소스 참조 (R.font.
)@FractionRes
: 퍼센트 리소스 참조 (R.fraction.
)@IdRes
: id 리소스 참조 (R.id.
)@IntegerRes
: integer 리소스 참조 (android.R.integer.
)@InterpolatorRes
: interpolator 리로스 참조 (android.R.interpolator.
)@LayoutRes
: layout 리소스 참조 (android.R.layout.
)@MenuRes
: menu 리소스 참조@NavigationRes
: navigation 리소스 참조 (R.navigation.
)@PluralsRes
: plurals(개수에 따른 문자열 표현) 리소스 참조getQuantityString
메서드처럼 아이템의 갯수에 따른 각각 다른 문자열을 표현하고 싶을 때 사용하는 resource 타입. [[참고사이트 #2]]@RawRes
: raw(원본 리소스. ex. txt, 음악 파일 등) 리소스 참조@StringRes
: string 리소스 참조@StyleableRes
: styleable 리소스 참조 (android.R.styleable.
)@StyleRes
: style 리소스 참조 (android.R.style.
)@TransitionRes
: transition(전환 애니메이션 효과) 리소스 참조@XmlRes
: XML 리소스 참조
Thread 관련 Annotation
메소드에 해당 Annotation이 붙은 경우 해당 스레드에서 호출될 수 있음을 나타낸다.
클래스에 붙은 경우 클래스의 모든 메소드는 해당 스레드에서 호출 될 수 있다.
@AnyThread
: 모든 스레드에서 호출 가능.@BindThread
: 바인더 스레드에서만 호출 가능. (서비스의 별도 스레드)@MaintThread(@UiThread)
: 메인 (UI) 스레드에서만 호출 가능.@WorkerThread
: worker(백그라운드 작업 같은 오래 걸리는 작업) 스레드에서만 호출 가능.
그 밖의 유용한 Annotation
@CallSuper
: 해당 Annotation이 붙은 메서드를 하위 클래스에서 오버라이드할땐 반드시 상위 클레스의 메서드를 호출하도록 강제함을 나타냄.- ex) Activity의 Lifecycle*
@CheckResult
: 해당 Annotation이 붙은 메서드가 리턴한 결과값을 개발자가 따로 사용하지 않고 무시했을 때 오류를 발생.
@CheckResult
fun trim(s: String) = s.trim()
...
s.trim() // 결과값을 따로 세팅하지 않아주었으므로 컴파일 에러 발생
val str = s.trim() // ok
@CheckSdkIntAtLeast
: 해당 Annotation이 추가된 메서드가SDK_INT API
레벨이 최소 주어진 값이 검사하고 결과를 반환하거나 지정된 람다식을 실행.
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
fun isAtLeastO() = Build.VERSION.SDK_INT >= 26
// 어노테이션의 인자로 들어갈 수 있는 속성은 다음과 같습니다.
// api: Int -> 최소 API
// codename: String -> 최소 API의 코드명("R")
// lambda: Int -> 최소 API 레벨을 만족할 경우 실행될 람다의 파라미터 번호
// parameter: Int -> 최소 API 레벨이 파라미터에 지정되며 첫 번째 파라미터 번호는 0부터 시작입니다.
@ChecksSdkIntAtLeast(parameter = 0, lambda = 1)
inline fun fromApi(value: Int, action: () -> Unit) {
if (Build.VERSION.SDK_INT >= value) {
action()
}
}
// 0번째 파라미터에 최소 API 레벨을 주었으며 1번째 파라미터에 실행될 람다식을 넣어줌을 뜻합니다.
// Kotlin 프로퍼티에도 사용 가능
@get:ChecksSdkIntAtLeast(api = Build.VERSION_CODES.GINGERBREAD)
val isGingerbread: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD
@ContentView
: 생성자에 연결할 수 있는 Annotation이며LayoutRes
를 생성자의 인자로 받으면setContentView
를 대체해준다.
class MainFragment: Fragment {
fun MainFragment() {
// 아래 생성자는 @ContentView 어노테이션이 연결되어 있습니다.
super(R.layout.main)
}
}
// Fragment 내부 코드
@ContentView
public Fragment(@LayoutRes int contentLayoutId) {
this();
mContentLayoutId = contentLayoutId;
}
@DoNotInline
: 코드가 빌드 시 최적화 할 때 Annotation 이 연결된 메소드는 인라인으로 변경되지 않아야 함을 나타낸다.
이는 일반적으로 별도의 클래스에 포함되도록 의도적으로 라인 외부 메서드의 인라인을 방지하는 데 사용한다.@GuardedBy
: 해당 필드나 메소드를 사용하려면Lock
를 보유해야하만 접근할 수 있다는 것을 의미한다.
private val anyLock = Any()
@GuardedBy("anyLock") // anyLock 객체를 보유해야 필드 접근 가능
@Volatile
private var lockObject : Any? = null
fun getLock(): Any? {
synchronized(anyLock) {
if (lockObject == null) {
lockObject = Any()
}
}
return lockObject
}
@Keep
: 빌드 시 코드가 최적화 될 때 Annotation 이 연결된 요소를 제거하지 않아야 함을 나타낸다.@OptIn
: Annotation 이 연결된 파일, 선언, 식에서opt-in API
를 사용할 수 있다. [[참고사이트 #3]]
@RequiresOptIn
: 해당 Annotation 이 연결된 요소가opt-in API
의 마커임을 나타낸다. 불안정하거나 비표준 API의 일부로 간주되며 해당 요소를 호출하려면OptIn
을 사용하거나@OptIn
Annotation 을 달아야 한다.@RequiresApi
: 해당 Annotation 은@TargetApi
와 유사하게 지덩된 API레벨 이상에서만 호출되어야 함을 의미하지만, 해당 메소드에 대한 호출자의 요구사항임을 더욱 명확하게 나타낸다.@RequirePermission
: 하나 이상의 권한이 필요하거나 필요할 수 있음을 나타내는 Annotation 이다.
// 단일 권한이 필요한 예
@RequiresPermission(ACCESS_COARSE_LOCATION)
abstract fun getLastKnownLocation(String provider): Location
// 하나 이상의 권한을 요구하는 예
@RequiresPermission(
anyOf = { ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION }
)
abstract fun getLastKnownLocation(String provider): Location
// 여러 권한이 필요한 예
@RequiresPermission(
allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}
)
abstract fun getLastKnownLocation(String provider): Location
// Content Provider에 대해 별도의 읽기 및 쓰기 권한을 요구하는 예
@RequiresPermission.Read(
@RequiresPermission(READ_HISTORY_BOOKMARKS)
) @RequiresPermission.Write(
@RequiresPermission(WRITE_HISTORY_BOOKMARKS)
)
const val BOOKMARKS_URI = Uri.parse("content://browser/bookmarks")
// 매개 변수에 지정된 경우 어노테이션은 메소드에 매개 변수 값에 따른 권한이 필요함을
// 나타냅니다.
fun startActivity(@RequiresPermission intent: Intent) { ... }
@RestrictTo
: 해당 요소는 특정 범위 내에서만 액세스해야 함을 나타낸다. (ex. Scope)
// 라이브러리 내 사용 제한 예(Group Id)
@RestrictTo(GROUP_ID)
fun resetPaddingToInitialValues() { ... }
// 테스트에서만 사용 제한 예
@RestrictScope(TESTS)
abstract fun getUserId(): Int
// 서브 클래시에서만 사용을 제한하는 예
@RestrictScope(SUBCLASSES)
fun onDrawForeground(canvas: Canvas) { ... }
@VisibleForTesting
: 선택적으로 가시성을 지정할 수 있다. 기본적으로 테스팅용으로만 공개될 수 있게 지정된다.
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
fun printDiagnostics(): String { ... }
// NONE -> 인자가 없을 시 기본 지정. 해당 요소는 테스트에서만 호출되어야 합니다.
// PACKAGE_PRIVATE -> 패키지 비공개 가시성을 갖습니다.
// PRIVATE
// PROTECTED
@ColorInt
: 패킹된 색상 int 를 나타냄을 의미한다.@Dimension
: 변수, 필드 또는 메소드의 반환 값이dimension
을 나타낼 것으로 예상됨을 나타낸다.unit
인수로 DP(0), PX(1), SP(2) 를 지정할 수 있다.@px
: 변수, 필드 또는 메소드의 반환 값이pixel dimension
임을 나타낸다.@FloatRange, @IntRange
: 각각 주어진 범위에서float
또는duoble
,int
이어야 함을 나타낸다.
@FloatRange(from=0.0, to=1.0)
fun getAlpha(): Float { ... }
@Size
: Annotation 이 연결된 요소가 주어진 크기 또는 길이를 가져야함을 나타낸다. (-1 은 설정되지 않음을 의미한다.)
fun getLocationInWindow(@Size(2) location: IntArray) { ... }
Size(value: Long, min: Long, max: Long, multiple: Long)
// value -> 정확한 크기 지정
// min -> 최소 크기
// max -> 최대 크기
// multiple -> 해당 인자의 배수 크기
틀린부분이 있거나, 궁금하신게 있거나, 그냥 아무말이나 하고싶으면 댓글 남겨주세요 🥴
봐주셔서 감사합니다 🥰
반응형
LIST
'Android (이론)' 카테고리의 다른 글
[Android] Context (0) | 2024.06.06 |
---|---|
[Android] MainThread & Handler (0) | 2024.05.05 |
[Android] ANR 이란? (0) | 2023.09.10 |
[ Kotlin ] Kotlin 과 Java 차이점 1 - 변수와 자료형 (0) | 2022.01.18 |
[Android] 안드로이드 Intent란? (0) | 2022.01.04 |
Comments