Skip to main content

Android : Enums Vs Magic Constants

I was recently introduced to IntDef and StringDef interfaces by a co worker. I was using enums to maintain a list of constants for some purpose and he suggested me to use these interfaces. I went ahead to read more on that and would be sharing here what I learned.


So, it turns out that enums often require more than twice as much memory as static constants (quoted from andev docs). They are class objects, so :


  • A single reference to an enum constant occupies 4 bytes
  • Every enum occupies space that is the sum of all its fields’ sizes and overhead of an object
  • the class itself occupies some space.

Whereas constants require fixed space, 4 bytes in case of an int constant and (num of chars) * 1 bytes in a string constant.


That said, we can replace enums with constants only in cases where we are just using them as constants. In cases where we are


  • storing more (or complex data) data in enums, or
  • using method overloading (every enum constant can have it’s own implementation of a method)

we’ll have to go with enums.


Now, I’ll be explaining how to use these interfaces.


We declare them as following :




    @StringDef({NotificationAction.DISPLAYED, NotificationAction.CONTENT_CLICKED,
        NotificationAction.ACTION_CLICKED, NotificationAction.DISMISSED})
    @Retention(RetentionPolicy.SOURCE)
    public @interface NotificationAction {
        String DISPLAYED = "Displayed";
        String CONTENT_CLICKED = "ContentClicked";
        String ACTION_CLICKED = "ActionClicked";
        String DISMISSED = "Dismissed";
    }

That’s it ! Now you can directly use them for annotating fields or method parameters in your code.


Fields :


@NotificationAction String action;

action = "dummy" // doesn't work
action = NotificationAction.DISPLAYED; // works

Methods :


public void actOnAction(@NotificationAction action){}

actOnAction("dummy") // doesn't work
actOnAction(NotificationAction.DISMISSED) // works

This way, it also makes it convenient to allow only certain values at these places.


It won’t improve your app’s performance by a significant bit but yeah, small things like this do count.


Let me know in case of any doubts.


Cheers !


Ref : http://stackoverflow.com/questions/29183904/should-i-strictly-avoid-using-enums-on-android

Comments

Popular posts from this blog

Android : AbsSavedState cannot be cast to $SavedState

Android AbsSavedState cannot be cast to <View>$SavedState I came across a strange crash today. This is the stacktrace : Fatal Exception: java.lang.ClassCastException: android.view.AbsSavedState$1 cannot be cast to android.widget.ScrollView$SavedState at android.widget.ScrollView.onRestoreInstanceState(ScrollView.java:1810) at android.view.View.dispatchRestoreInstanceState(View.java:14768) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3123) at android.view.View.restoreHierarchyState(View.java:14746) at android.support.v4.app.Fragment.restoreViewState(SourceFile:470) at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1326) at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(SourceFile:2323) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(SourceFile:2136) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(SourceFile:2092)

Android Tip : Handling back button in Fragments

Android Tip : Handling hardware back button in Fragment and DialogFragment This post explains how to handle hardware back button in a Fragment OR DialogFragment . In DialogFragment, it’s quiet straight forward to achieve this. You’ve to get the dialog instance and set onKeyListener on it : if (getDialog() != null ) { getDialog().setOnKeyListener( new DialogInterface.OnKeyListener() { @Override public boolean onKey (DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { Timber.i( "hardware back button pressed" ); } } }); } This can be done in the onViewCreated callback. For fragments, this method doesn’t work and fragments doesn’t have a direct callback to catch this event. So in this case, the approach that we follow is : You

DialogFragment : NullPointerException (support library)

Another weird crash this time ! Here’s the stack trace : Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{<activity.fully.qualified.path>}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Dialog.setContentView(android.view.View)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2659) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2724) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4524) at android.app.ActivityThread.-wrap19(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6123) at java.lang.reflect.Method.invoke(Method.java) at com.android