Learn to write good code in Android: Starter Pattern

Writing code in Android is not a big task. All you need to do is just follow some articles or tutorials and write the code for an Android application. But what makes you different from other Android developers is the quality of code that you may write for the same application. A good Android code not only distinguishes you from other developers but also helps in avoiding some of the Runtime errors that might not be discovered by you or the Android at compile time.

So, in this blog, we will learn how to write good code in Android by using the Starter Pattern. So, let’s get started.

What’s the problem?

Before looking at the solution, we should first know what’s the real problem. Let’s take an example to understand the scenario in a better way.

Here, in our example, we are having one PostDetailActivity that is containing the details of a post i.e. title and image url. Also, this PostDetailActivity is started from two activities namely MainActivity and PostListActivity by passing the title and image url. We are having a constant class also to declare constant values. So, the code for the constant class is:

object Constants {

    internal const val EXTRAS_POST_TITLE = "post_title"
    internal const val EXTRAS_POST_IMAGE_URL = "post_image_url"

}

Code for the PostDeatilsActivity is:

class PostDetailActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_detail)

        val postTitle = intent.getStringExtra(Constants.EXTRAS_POST_TITLE)
        val postImageUrl = intent.getStringExtra(Constants.EXTRAS_POST_IMAGE_URL)
    }
}

Code for the MainActivity is:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val intent = Intent(this@MainActivity, PostDetailActivity::class.java)
        intent.putExtra(Constants.EXTRAS_POST_TITLE, "title")
        intent.putExtra(Constants.EXTRAS_POST_IMAGE_URL, "imageUrl")
        startActivity(intent)
    }
}

Code for PostListActivity is:

class PostListActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_list)

        val intent = Intent(this@PostListActivity, PostDetailActivity::class.java)
        intent.putExtra(Constants.EXTRAS_POST_TITLE, "title")
        intent.putExtra(Constants.EXTRAS_POST_IMAGE_URL, "imageUrl")
        startActivity(intent)
    }
}

So, at this point of time, is everything OK with the code? It should perform well. But the problems arises when you are working in a collaborative environment i.e. more than one developers are working on the same project.

For example, let’s say that at some point of time you need to add a thumbnail image to your application. So, what you will do is just add one const value in the Constant class:

object Constants {

    internal const val EXTRAS_POST_TITLE = "post_title"
    internal const val EXTRAS_POST_IMAGE_URL = "post_image_url"
    internal const val EXTRAS_POST_THUMBNAIL_IMAGE_URL = "post_thumbnail_image_url"

}

At the same time you have to add the thumbnail url to your PostDetailActivity:

val postImageThumbnailUrl = intent.getStringExtra(Constants.EXTRAS_POST_THUMBNAIL_IMAGE_URL)

Since you are not the only person working on the project. Some fellow developer may pass the thumbnail url in the MainActivity but forgot to add the same in the PostListActivity. Here, you will never encounter a compile time error. But whenever you are using the application and specifically the PostListActivity, then you will encounter some bug and these things should be removed at the coding time only. Also, if you are working on a big project then these constants can be of larger numbers and you need to add each and every constant in the activity that is calling the PostDetailActivity.

Always be on the safer side, but also have the knowledge of the danger side

The solution

So, we have discussed the problem that might happen with any developer. Instead of writing the correct code(syntax wise), you may encounter some bugs at the runtime.

The above problem can be removed by writing the code in Starter Pattern.

In the Starter Pattern, we use some static methods to start with the values which are to be used in our activity. Instead of having a separate constant class for the constant values, we can declare the required values of a class in the same class. So, whenever needed, you can access those variables from that class only.

The code of PostDeatilActivity will become:

class PostDetailActivity : AppCompatActivity() {

    companion object {
        //constants
        internal const val EXTRAS_POST_TITLE = "post_title"
        internal const val EXTRAS_POST_IMAGE_URL = "post_image_url"

        //starter function
        fun getStartIntent(context: Context, postTitle: String, postImageUrl: String): Intent {
            val intent = Intent(context, PostDetailActivity::class.java)
            intent.putExtra(EXTRAS_POST_TITLE, postTitle)
            intent.putExtra(EXTRAS_POST_IMAGE_URL, postImageUrl)
            return intent
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_detail)

        val postTitle = intent.getStringExtra(EXTRAS_POST_TITLE)
        val postImageUrl = intent.getStringExtra(EXTRAS_POST_IMAGE_URL)

    }
}

In the above code, we are putting the extras values in the getStartIntent() function and getting the value in the onCreate().

Now, you can call the PostDetailActivity from the MainActivity by using the below code:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = PostDetailActivity.getStartIntent(this@MainActivity, "title", "imageUrl")
        startActivity(intent)
    }
    
}

But, here is a catch. If we add some more extras to our PostDetailActivity, then you must have to pass the newly added value from the activity that is calling the PostDetailActivity. For example, of we add the below extras in the PostDetailActivity:

class PostDetailActivity : AppCompatActivity() {

    companion object {
        //constants
        internal const val EXTRAS_POST_TITLE = "post_title"
        internal const val EXTRAS_POST_IMAGE_URL = "post_image_url"
        internal const val EXTRAS_POST_THUMBNAIL_URL = "post_image_thumbnail_url"

        //starter function
        fun getStartIntent(context: Context, postTitle: String, postImageUrl: String, postImageThumbailUrl: String):Intent {
            val intent = Intent(context, PostDetailActivity::class.java)
            intent.putExtra(EXTRAS_POST_TITLE, postTitle)
            intent.putExtra(EXTRAS_POST_IMAGE_URL, postImageUrl)
            intent.putExtra(EXTRAS_POST_THUMBNAIL_URL, postImageThumbailUrl)
            return intent
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_detail)

        val postTitle = intent.getStringExtra(EXTRAS_POST_TITLE)
        val postImageUrl = intent.getStringExtra(EXTRAS_POST_IMAGE_URL)
        val postImageThumbnailUrl = intent.getStringExtra(EXTRAS_POST_THUMBNAIL_URL)

    }
}

Here, we are adding one more field i.e. the thumbnail url.

In this case, if you forgot to pass the thumbnail url from any activity calling the PostDetailActivity, then you will get a compile-time error and you can then add the desired variable or pass the desired variable. Following is the example of the MainActivity:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = PostDetailActivity.getStartIntent(this@MainActivity, "title", "imageUrl", "imageThumbnailUrl")
        startActivity(intent)
    }

}

By using the Starter Pattern, you will never encounter these run time errors that we have discussed in the blog.

Conclusion

In order to write good code in Android and to stand out of the queue, you should start using the Starter Pattern. The Starter Pattern is used to write the code in such a way that we start the variables in the same Activity using that variable. This will reduce the runtime errors and also help in detecting the errors if any while developing a group project.

You can watch the video of the same on our Youtube Channel.

Keep Learning :)

Team MindOrks!