In my previous post, we talked about setting baseAligned false and how it’s improving android application performance. Today we are going to look into couple of practices around defining constants for bundle keys used between two activities.
Since I am technical leading a team of android engineers, I have observed question “Should we define constants for bundle keys?”, “What is the best way to define constants for bundle keys” and I am sure many android developers are putting hard coded key strings values into bundle and passing it to next activity where they again use hard coded key strings to access bundle values. Do you see this is not a good practice!
Couple of points why it’s a bad practice:
- If you change bundle key values and forgot to change it in destination activity(s) then it would be an issue!
Suppose you are accessing bundle values in Activity Z, and you want to find out which one is the source activity from which this intent data is coming! - If you define constants for bundle keys then it would be easier to sort out and manage above 2 points perfectly.
Share some best practices
Now your expression should be like hey Paresh, show me some best practices for defining bundle key constants, getting intent ready for starting activity and re-factoring legacy code to update with the best practice you shared here.
Practice 1: Defining constants for bundle keys
I have seen some android developers wrapping their key constants in inner-class like
public class DestinationActivity extends AppCompatActivity { public static class Key { public static final String USER_NAME = "USER_NAME"; public static final String IS_LOGGED_IN = “IS_LOGGED_IN”; public static final String USER_PROFILE_PIC = “USER_PROFILE_PIC”; }
but I would say it’s not required to wrap key constants in inner class but declaring them at activity level are enough.
For example:
public class DestinationActivity extends AppCompatActivity { public static final String KEY_USER_NAME = “USER_NANE”; public static final String KEY_IS_LOGGED_IN = “IS_LOGGED_IN”; public static final String KEY_USER_PROFILE_PIC = “USER_PROFILE_PIC”; }
Practice 2: Preparing intent and starting activity
What majority android developers are doing is they prepare intent for Activity B and start it from Activity A.
Instead how about preparing intent for B in Activity B, so it would be easier for separating code between activities and keeping that particular activity related code in its own class.
For example:
public class DestinationActivity extends Activity { public static final String KEY_USER_NAME = “USER_NANE”; public static final String KEY_IS_LOGGED_IN = “IS_LOGGED_IN”; public static final String KEY_USER_PROFILE_PIC = “USER_PROFILE_PIC”; public static Intent prepareIntent(Context context, String userName, boolean isLoggedIn, Uri userPhoto) { Intent intent = new Intent(context, SecondActivity.class); intent.putExtra(KEY_USER_NAME, userName); intent.putExtra(KEY_IS_LOGGED_IN, isLoggedIn); intent.putExtra(KEY_USER_PROFILE_PIC, userPhoto); return intent; }
so now whenever you want to prepare intent for Destination activity and start it, then you need to write:
startActivity(DestinationActivity(userName, isLoggedIn, userPhoto));
Now, what if you want to put more arguments into bundle:
- Then either you can follow builder pattern in building intent
- Or if only 1-2 more arguments then can include arguments in constructor
- Or you can get an Intent object using prepareIntent() in source activity and can pass on more parameters but I think this 3rd point is not a good practice!
Practice 3: Refactoring code of legacy or already developed android project
There is a question how would I find out hardcoded key strings easily because checking one by one classes is not a proper solution. Well, “lint” is always a best friend which would help you in finding out hard-coded strings across the project, now you will have to check one by one hard-coded strings. Yes it’s not easy to refactor legacy code but this is a standard but tricky solution!
To run this specific inspection on hard coded strings, just select Analyse menu -> Run inspection by name…
To summarise
Ultimately these mentioned practices would make your code more readable and mistakes free because you are removing hard-coded strings. I Hope you have learnt from mentioned best practices, if you know best practices around it then please share it with me!