Clock 2 Min Read

Ways to Get Rid of Boilerplate Using Kotlin Extensions

blank

Kumar

CalnderJanuary 20, 2020
Ways to Get Rid of Boilerplate Using Kotlin Extensions

It goes without saying that Kotlin has transformed Android app development by simplifying the entire process. Developers now find it quite easier to create quality apps even without spending much time. Not only the development, it also enables developers to easily deal with the bug and makes apps glitch-free.

In this blog, we are going to explain the important ways of removing boilerplate with the use of Kotlin extensions.

To initiate the task, developers first choose a simple custom view, then MyView, subclasses TextView. One can consider it as custom view has an associated styleable

xml.

<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<declare-styleable name=”MyView”>
<attr name=”theText” format=”string”/>
</declare-styleable>
</resources>

Developers get the option to incorporate custom view into a complete layout with the use of the attribute.

theText:

<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
xmlns:app=”http://schemas.android.com/apk/res-auto”>

<com.caine.allan.specialview.MyView
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
app:theText=”Hello World!!!”/>

</FrameLayout>

When it comes to steps to get an attribute from an xml, you can use the same process every time for this.

● You can use Context.obtainStyledAttributes(…) to get TypedArray.

● Methods of the TypedArray are useful to assign a complete attribute value to various class properties in the form of try block.

● Recycling of TypedArray is done in a finally block.

If you use Kotlin Extension without simplification, then you will be able to get the final implementation of MyView as below.

class MyView(context: Context, attributeSet: AttributeSet? = null)
: TextView(context, attributeSet) {

init {
val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.MyView, 0, 0)

try {
text = typedArray.getString(R.styleable.MyView_theText)
} finally {
typedArray.recycle()
}

}
}

In the above coding section, line 5, line 8, and line 10 are directly related to step 1, step 2, and step 3 respectively.

The simplification work is started by observing that the line 8 in the try/finally block is completely unique to MyView.The remaining else is nothing but the boiler plate. One can relegate the try/finally block to a Kotlin extension of TypedArray:
fun TypedArray.use(block: TypedArray.() -> Unit) {
try {
block()
} finally {
this.recycle()
}
}

MyView class can also be simplified as below;

class MyView(context: Context, attributeSet: AttributeSet? = null)
: TextView(context, attributeSet) {

init {
val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.MyView, 0, 0)

typedArray.use {
text = getString(R.styleable.MyView_theText)
}
}
}

One can read the line as;

text = getString(R.styleable.MyView_theText)

It is basically the block described in lines 1 and 3 of the ViewCreateUtils.

The code which looks completely unique to MyView is then passed completely to TypedArray.use(block: TypedArray.() -> Unit)that is perceived as a lambda function.

One can also find the scope of further simplification. You can also use the same way to obtain the TypedArray from the Context, when it comes to custom views.

fun Context.getStyledAttributes(attributeSet: AttributeSet?, styleArray: IntArray, block: TypedArray.() -> Unit) =

this.obtainStyledAttributes(attributeSet, styleArray, 0, 0).use(block)

You can take a glimpse of final simplification of MyView as;

class MyView(context: Context, attributeSet: AttributeSet? = null)
: TextView(context, attributeSet) {

init {
context.getStyledAttributes(attributeSet, R.styleable.MyView) {
text = getString(R.styleable.MyView_theText)
}
}
}

You will not be able to find TypedArray in the simplified code. When it comes to extension function, it functions by getting TypedArray from it. You will not be able to find try/finally block there. The use extension function generally runs line 6 in a try block.

With the use of lambdas and extension functions, you will be able to see the initializer function will go from.

init {
val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.MyView, 0, 0)

try {
text = typedArray.getText(R.styleable.MyView_theText)
} finally {
typedArray.recycle()
}
to
init {
context.getStyledAttributes(attributeSet, R.styleable.MyView) {
text = getString(R.styleable.MyView_theText)
}

Related Posts

How Mobile Apps Are Transforming the eCommerce Industry - iWebServices

How Mobile Apps Are Transforming the eCommerce Industry?

mobility

‘Mobile Apps + eCommerce industry‘  These above two terms are a blasting combination that many…

Read More ArrowRight
What is the Cost of Developing Car Parking App?

What is the Cost of Developing a Car Parking App?

mobility

Are you tired of circling around the block, looking for a parking spot? Or worse,…

Read More ArrowRight
The Future of Media and Entertainment How Mobile Apps are Transforming the Industry in 2023 and Beyond - iWebServices

The Future of Media & Entertainment: How Mobile Apps are Transforming the Industry in 2023 and Beyond?

mobility

Are you interested in developing the next big entertainment app? However, are you unsure whether…

Read More ArrowRight
ArrowRight-green-icon