I used to define a set of related constants like Bundle
keys together in an interface like below:
public interface From{ String LOGIN_SCREEN = "LoginSCreen"; String NOTIFICATION = "Notification"; String WIDGET = "widget"; }
This provides me a nicer way to group related constants together and used them by making a static import (not implements). I know Android
framework also uses the constants in same way like Toast.LENTH_LONG
, View.GONE
.
However, I often feel that the Java Enums
provide much better and powerful way to represent the constant.
But is there a performence issue in using enums
on Android
?
With a bit of research I ended up in confusion. From this question "Avoid Enums Where You Only Need Ints” removed from Android's performance tips? it's clear that Google
has removed "Avoid enums" from its performance tips, but from it's official training docs Be aware of memory overhead section it clearly says: "Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android." Is this still holds good? (say in Java
versions after 1.6)
One more issue that I observed is to send enums
across intents
using Bundle
I should send them by serializing (i.e putSerializable()
, that I think an expensive operation compared to primitive putString()
method, eventhough enums
provides it for free).
Can someone please clarify which one is the best way to represent the same in Android
? Should I strictly avoid using enums
on Android
?
Many people consider Enums as a code smell and an anti-pattern in OOPs. Certain books have also cited enums as a code smell, such as the following. In most cases, enums smell because it's frequently abused, but that doesn't mean that you have to avoid them. Enums can be a powerful tool in your arsenal if used properly.
Enums are lists of constants. When you need a predefined list of values which do represent some kind of numeric or textual data, you should use an enum. You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values.
Enums are used when we know all possible values at compile-time, such as choices on a menu, rounding modes, command-line flags, etc. It is not necessary that the set of constants in an enum type stay fixed for all time. In Java (from 1.5), enums are represented using enum data type.
The enums are type-safe means that an enum has its own namespace, we can't assign any other value other than specified in enum constants. Typesafe enums are introduced in Java 1.5 Version. Additionally, an enum is a reference type, which means that it behaves more like a class or an interface.
Use enum
when you need its features. Don't avoid it strictly.
Java enum is more powerful, but if you don't need its features, use constants, they occupy less space and they can be primitive itself.
method overloading - every enum constant has its own implementation of a method
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); }
more data - your one constant contains more than one information that cannot be put in one variable
you can accept continuous data
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); } ... } }
If the enums simply have values, you should try to use IntDef/StringDef , as shown here:
https://developer.android.com/studio/write/annotations.html#enum-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++ .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With