본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] 추가된 유용한 annotations

by 돼지왕 왕돼지 2017. 8. 2.
반응형

 [android] 추가된 유용한 annotations



http://tools.android.com/tech-docs/support-annotations

https://developer.android.com/reference/android/support/annotation/package-summary.html

@anyres, @binderthread, @callSuper, @checkresult, @ColorInt, @colorres, @drawableres, @floatrange, @interface, @interpolatorres, @intrange, @mainthread, @nonnull, @nullable, @size, @stringdef, @stringres, @uithread, @workerthread, access_coarse_location, access_fine_location, allof, Android, annotation 정의, Annotations, anyof, API, array, class thread annotation, collection, Color Integers, Compile, enforcePermission, flag, Flavour, function, intdef, IntDef and StringDef Annotations, lint, lint check bug, manifest, Max, Method, Min, Multiple, nonnull, nullness, Nullness annotations, overriding methods, permission, Read, READ_HISTORY_BOOKMARKS, RequiresPermission, resource type, Resource Type Annotations, return values, set_wallpaper, string, stringdef, suggest, suggest argument, support library, Threading Annotations, uithread, URI, validate, variable, wraning, write, WRITE_HISTORY_BOOKMARKS, [android] 추가된 유용한 annotations


-

Android support library 19.1 version 에서 annotation 들을 추가했다.



-

이 녀석을 사용하려면 gradle 에 다음을 추가해야 한다.


compile ‘com.android.support:support-annotations:20.0.0’


여기서는 크게 3가지 형태의 annotation 을 제공한다.


1. Nullness annotattions

2. Resource type annotations

3. IntDef and StringDef annotations




Nullness annotations


-

@NonNull


이 녀석은 전달되는 param 이 null 이어서는 안 된다는 것을 의미한다.

만약 명시적으로 null 이 전달되는 case 라면 warning 을 표시하게 된다.



-

@Nullable


null 이 가능함을 나타낸다.



-

method 위에 @NonNull 이나 @Nullable 을 붙이면 return type 에 대한 명시를 이야기한다.




Resource Type Annotations


-

전달받는 resource 의 type 을 명시할 수 있다.


void sayHello(@StringRes int id){

     ...

}


만약 여기에 전달되는 id 가 string res 가 아니라면 error 를 표시한다.



-

@StringRes, @DrawableRes, @ColorRes, @InterpolatorRes 등등이 있다.

@AnyRes 도 가능하다.




IntDef and StringDef Annotations


-

IntDef 나 StringDef 는 Annotation 을 정의해서 사용할 때 전달되는 값을 validate 할 수 있어서 좋다.


public class IceCreamFlavourManager {


    private int flavour;


    public static final int VANILLA = 0;

    public static final int CHOCOLATE = 1;

    public static final int STRAWBERRY = 2;


    @IntDef({VANILLA, CHOCOLATE, STRAWBERRY})

    public @interface Flavour {

    }


    @Flavour

    public int getFlavour() {

        return flavour;

    }


    public void setFlavour(@Flavour int flavour) {

        this.flavour = flavour;

    }


}


위와 같이 Flavour annotation 을 정의하여 사용하면,

param 으로 전달되는 값이 정의한 3가지 값이 아니라면, error 를 표시한다.

덧붙여 IDE 에서 suggest argument 로도 작동을 한다.



-

@IntDef 를 flag 형태로 사용하고 싶다면 annotation 을 다음과 같이 정의하면 된다.

flag 를 사용한다는 것은 | & 연산을 할 수 있다는 것.

@IntDef(flag = true, value = {VANILLA, CHOCOLATE, STRAWBERRY})

public @interface Flavour {

}



-

@StringDef 는 @IntDef 와 동일하다 다만 String 의 형태이다.






Threading Annotations


-

Support lib 22.2 이상부터는 thread 에 관한 annotation 들도 추가되었다.



-

Threading Annotation 들은 function call 등의 범위를 정해준다.

다음의 4가지 annotation 이 있다.


@UiThread, @MainThread, @WorkerThread, @BinderThread 



-

만약 class 전체 method 가 thread 제약이 있다면 class 에 thread annotation 을 마킹할 수 있다.

예를 들면 View class 등이 있겠다.



-

app 이 다른 window 에서 작동하는 thread 를 만들 수 있다.

매우 rare 한 case 이기는 하지만, 이럴 경우에 @UiThread 와 @MainThread 를 구분할 일이 생길 수 있어 2개로 분기한다.

이런 rare 한 case 는 system level 에서만 발생하기 때문에 사실 @UIThread 와 @MainThread 는 혼용해서 사용할 수 있다.




Color Integers


-

Color Res 가 아닌 Color Int 를 받고 싶을 때는 @ColorRes 대신 @ColorInt 를 써주면 된다.

잘못된 값이 들어오면 error 를 발생시킨다.




Value Constraints


-

@Size, @IntRange, @FloatRange 등이 있다.


public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha){

     ...

}


위와 같이 range 를 줄 수 있다.



-

public void setAlpha(@IntRange(from=0,to=255) int alpha) {

     …

}



-

array, collection, string 등은 @Size 를 쓸 수 있다.

예를 들어

     non empty collection 이 와야 한다면 @Size(min=1)

     string 이 23자 이하여야만 하다면 @Size(max=23)

     array 가 정확히 2개의 element 만 가지고 있어야 한다면 @Size(2)

     array 가 2의 배수 size 를 가져야 한다면 @Size(multiple=2)




Permissions


-

@RequiresPermission(Manifest.permission.SET_WALLPAPER)


위와 같이 사용하면 된다.



-

둘 중 하나를 선택하는 경우는..

@RequiresPermission(anyOf = {

    Manifest.permission.ACCESS_COARSE_LOCATION,

    Manifest.permission.ACCESS_FINE_LOCATION})



-

여러개의 permission 을 요구하는 경우는...

@RequiresPermission(allOf = {

    Manifest.permission.READ_HISTORY_BOOKMARKS, 

    Manifest.permission.WRITE_HISTORY_BOOKMARKS})



-

이 permission annotation 은 function, variable (보통 상수) 모두 적용 가능하다.



-

다음과 같이, Uri 등에 적용할 때는 Read, Write 에 대한 permission 을 따로 정의할 수 있다.


@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))

@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))

public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");




Overriding Methods


-

@CallSuper 를 통해서 상속이 가능한 경우 sub class 가 반드시 super 를 호출하도록 만들 수 있다.



-

android 1.3 preview 에서 lint check bug 가 있다고 하니 100% 신뢰하진 말길..




Return Values - minor


-

@CheckResult 는 해당 함수의 return 값을 확인해야함을 이야기한다.

잘 사용되지는 않지만, 특정 api 를 착각하여 사용할 경우에 대한 lint 를 띄우기 위함인데..

다음과 같은 예가 있다.


@CheckResult(suggest="#enforcePermission(String,int,int,String)")

public abstract int checkPermission(@NonNull String permission, int pid, int uid);


개발자가 이 함수를 부르고선 enforcePermission 을 불렀다고 생각할 수 있다. ( 대체 함수 추천 )

그래서 checkPermission 의 return 값을 assign 해서 사용하지 않는다면 lint 로 경고를 띄워준다.




반응형

댓글