developer tip

Android에서 열거 형 사용을 엄격히 피해야합니까?

optionbox 2020. 9. 7. 08:03
반응형

Android에서 열거 형 사용을 엄격히 피해야합니까?


Bundle다음과 같은 인터페이스에서 키와 같은 관련 상수 세트를 함께 정의했습니다 .

public interface From{
    String LOGIN_SCREEN = "LoginSCreen";
    String NOTIFICATION = "Notification";
    String WIDGET = "widget";
}

이것은 관련 상수를 함께 그룹화하고 정적 가져 오기 (구현이 아님)를 만들어 사용하는 더 좋은 방법을 제공합니다. 내가 알고있는 Android프레임 워크도 같은 동일한 방법으로 상수를 사용합니다 Toast.LENTH_LONG, View.GONE.

그러나 나는 종종 Java Enums상수를 나타내는 훨씬 더 좋고 강력한 방법을 제공 한다고 느낍니다 .

그러나 사용의 성취도 문제가 enums에가 Android?

약간의 연구로 나는 혼란에 빠졌습니다. 이 질문에서 ? 안드로이드의 성능 정보에서 제거 "당신 만의 int 필요 않도록 열거 형" 는 것이 분명 Google제거했습니다 "피 열거 형을" 성능 팁에서, 그러나 그것의에서 공식 훈련 문서는 메모리 오버 헤드에주의 가 명확하게 말한다 절 : "열거 형을 종종 정적 상수보다 두 배 이상의 메모리가 필요합니다. Android에서 열거 형을 사용하는 것은 엄격히 피해야합니다. " 여전히 유효합니까? (예 : Java1.6 이후 버전)

내가 관찰 한 또 하나의 문제는 직렬화 하여 전송해야 함 enumsintents사용하여 Bundle전송하는 것입니다 (즉 putSerializable(), 기본 putString()메소드에 비해 비용이 많이 드는 작업이라고 생각하지만 enums무료로 제공하지만).

누군가 같은 것을 표현하는 가장 좋은 방법이 무엇인지 명확히 해줄 수 있습니까 Android? 에 사용 enums엄격히 피해야 Android합니까?


enum기능이 필요할 때 사용하십시오 . 엄격하게 피하지 마십시오 .

Java enum은 더 강력하지만 기능이 필요하지 않은 경우 상수를 사용하면 공간을 덜 차지하고 원시 자체가 될 수 있습니다.

열거 형을 사용하는 경우 :

  • 당신이 받아 들일 수 - 유형 검사 (내가 부르는 아래 참조 목록에 값을, 그들은 연속없는 연속 여기)
  • 메서드 오버로딩-모든 열거 형 상수에는 자체 메서드 구현이 있습니다.

    public enum UnitConverter{
        METERS{
            @Override
            public double toMiles(final double meters){
                return meters * 0.00062137D;
            }
    
            @Override
            public double toMeters(final double meters){
                return meters;
            }
        },
        MILES{
            @Override
            public double toMiles(final double miles){
                return miles;
            }
    
            @Override
            public double toMeters(final double miles){
                return miles / 0.00062137D;
            }
        };
    
        public abstract double toMiles(double unit);
        public abstract double toMeters(double unit);
    }
    
  • 더 많은 데이터-하나의 상수에 하나의 변수에 넣을 수없는 하나 이상의 정보가 포함되어 있습니다.

  • 복잡한 데이터-데이터를 조작하는 데 필요한 방법

하면 되지 열거를 사용하는 방법 :

  • 한 유형의 모든 값을 허용 할 수 있으며 상수에는 가장 많이 사용되는 값만 포함됩니다.
  • 연속 데이터를받을 수 있습니다.

    public class Month{
        public static final int JANUARY = 1;
        public static final int FEBRUARY = 2;
        public static final int MARCH = 3;
        ...
    
        public static String getName(final int month){
            if(month <= 0 || month > 12){
                throw new IllegalArgumentException("Invalid month number: " + month);
            }
    
            ...
        }
    }
    
  • 이름 (예를 들어)
  • 실제로 열거 형이 필요하지 않은 모든 것

열거 형은 더 많은 공간을 차지합니다.

  • 열거 형 상수에 대한 단일 참조는 4 바이트를 차지 합니다.
  • every enum constant occupies space that is a sum of its fields' sizes aligned to 8 bytes + overhead of the object
  • the enum class itself occupies some space

Constants occupy less space

  • a constant doesn't have a reference so it's a pure data (even if it's a reference, then enum instance would be a reference to another reference)
  • constants may be added to an existing class - it's not necessary to add another class
  • constants may be inlined; it brings extended compile-time features (such as null checking, finding dead code etc.)

If the enums simply have values, you should try to use IntDef/StringDef , as shown here:

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

Example: instead of :

enum NavigationMode {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS} 

you use:

@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

and in the function that has it as a parameter/returned value , use:

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

In case the enum is complex, use an enum. It's not that bad.

To compare enums vs constant values, you should read here:

http://hsc.com/Blog/Best-Practices-For-Memory-Optimization-on-Android-1

Their example is of an enum with 2 values. It takes 1112 bytes in dex file compared to 128 bytes when constant integers are used . Makes sense, as enums are real classes, as opposed to how it works on C/C++ .


Should I strictly avoid using enums on Android?

No. "Strictly" means they are so bad, they should not be used at all. Possibly a performance issues might arise in an extreme situation like many many many (thousands or millions of) operations with enums (consecutive on the ui thread). Far more common are the network I/O operations that should strictly happen in a background thread. The most common usage of enums is probably some kind of type check - whether an object is this or that which is so fast you won't be able to notice a difference between a single comparison of enums and a comparison of integers.

Can someone please clarify which one is the best way to represent the same in Android?

There is no general rule of thumb for this. Use whatever works for you and helps you get your app ready. Optimize later - after you notice there's a bottleneck that slows some aspect of your app.


In addition to previous answers, I would add that if you are using Proguard (and you should definitely do it to reduce size and obfuscate your code), then your Enums will be automatically converted to @IntDef wherever it is possible:

https://www.guardsquare.com/en/proguard/manual/optimizations

class/unboxing/enum

Simplifies enum types to integer constants, whenever possible.

Therefore, if you have some discrete values and some method should allow to take only this values and not others of the same type, then I would use Enum, because Proguard will make this manual work of optimizing code for me.

And here is a good post about using enums from Jake Wharton, take a look at it.

As a library developer, I recognize these small optimizations that should be done as we want to have as little impact on the consuming app's size, memory, and performance as possible. But it's important to realize that [...] putting an enum in your public API vs. integer values where appropriate is perfectly fine. Knowing the difference to make informed decisions is what's important


With Android P, google has no restriction/objection in using enums

The documentation has changed where before it was recommended to be cautious but it doesn't mention it now. https://developer.android.com/reference/java/lang/Enum


Two facts.

1, Enum is one of the most powerful feature in JAVA.

2, Android phone usually has a LOT of memory.

So my answer is NO. I will use Enum in Android.


I like to add, that you can not use @Annotations when you declare a List<> or Map<> where either key or value is of one of your annotation interfaces. You get the error "Annotations are not allowed here".

enum Values { One, Two, Three }
Map<String, Values> myMap;    // This works

// ... but ...
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;

@Retention(RetentionPolicy.SOURCE)
@IntDef({ONE, TWO, THREE})
public @interface Values {}

Map<String, @Values Integer> myMap;    // *** ERROR ***

So when you need to pack it into a list/map, use enum, as they can be added, but @annotated int/string groups can not.

참고URL : https://stackoverflow.com/questions/29183904/should-i-strictly-avoid-using-enums-on-android

반응형