Mention enums to Android students, and many of you will probably think: “Don’t use enums in Android. They take up more memory. Use annotations instead.” If you’re confused and skeptical, do a Google search, like the one below.
And is that really the case? Now that every Android phone has 6GB or more of ram in 2019, does the phrase “enumerations are not recommended in Android” still apply?
Historical background
A lot of people believe that, without a doubt, because of what the official document says.
It was written in the official Android document in 2009, when Android was still in its infancy. It was written by the core Android developers, influenced by the hardware of the phone at the time, and it seemed true at the time, but now a decade later, We can no longer find this sentence in the official Android documentation for 2019. According to StackOverflow, the Android team changed this sentence after the release of Android P.
I also found some advice from JakeWharton on using enumerations in Android:
JW believes that ProGuard and R8 will optimize trivial enumerations to integers at compile time. There is no problem with inefficiency. Enum inefficiency is just a rumor spread by the Android team. And Kotlin and the Enum in Java are the same after being encoded into bytecode.
On Reddit, JW also responded:
Some people argue that the statement in the official documentation is incorrect and misleading, and that there is a memory overhead when you use enumerations as IntDef only.
JW responded: “We’ve all ignored the fact that Enum is a complete class that implements interfaces, implements its own methods, and when you don’t, ProGuard optimizes enumerations to integers, which was completely wrong at the time, and has always been wrong.”
Enumerations aren’t that scary
enum class Type { ONE, TWO }
Copy the code
When we define such a simple enumeration, decompile the code and we’ll find something like this:
public final class MainActivity$WhenMappings { public static final int[] $EnumSwitchMapping$0 = new int[Type.values().length]; static { $EnumSwitchMapping$0[Type.ONE.ordinal()] = 1; $EnumSwitchMapping$0[Type.TWO.ordinal()] = 2; }}Copy the code
The compiler will help us optimize the enumeration to an int array, which is automatically optimized, but only if, as JW says, we simply use the fields defined in the enumeration and do not use it as a full class, calling its own methods, such as toString(), name, etc.
Instead you use annotations to implement:
const val ONE = 1
const val TWO = 2
@IntDef(ONE, TWO)
@Retention(AnnotationRetention.SOURCE)
annotation class Type
Copy the code
In fact, such optimization is not worth the cost, it loses the maintainability of the code to some extent, and Kotlin’s support for this approach is not very good, we should focus on other things that have a higher input/output ratio.
More often than not, we don’t need to worry too much about the memory growth associated with Enum. Remember that Enum is a class, and it just takes up as much memory as it should as a class.
You may have noticed from previous Android SDK that official code uses things like @intdef instead of enums a lot, but I recently looked at the code in Android Jetpack and official developers also use enUms a lot in their code. For example, Lifecycle:
Better use of enums in Kotlin
In Koltin, we may also use an Enum Class, Sealed Class, to achieve the same functionality.
Sealed classes are used to represent a restricted class inheritance structure: when a value can have a finite number of types and no other types. In a sense, they are an extension of enumerated classes: the collection of values of enumerated types is also limited, but only one instance of each enumerated constant exists, whereas a subclass of a sealed class can have multiple instances of containable state.
There are a few things to note about using sealed classes:
- You need to add the sealed modifier before the class name
- All subclasses must be declared in the same file as the sealed class itself
- Sealed classes are themselves abstract
- Sealed classes are not allowed to have non-private constructors
A common usage scenario is to use Sealed Class to declare the status of network requests
For more information about Sealed Class usage, please refer to Kotlin’s official documentation.
Therefore, my opinion about the use of Enum is that it should be used without worrying too much about the growth of memory. Enum has many convenient features, and the convenience of coding brought by Enum and the improvement of code readability are also very good.
If you find this article interesting, be sure to share and forward it to 😝.
Welcome to the wechat public account of the same name [Android | Kotlin]