Contact Us

Table of Contents

Reading Time: 2 minutes

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)
}

Kumar A
Kumar A

Online-Meeting

Subscribe to our email newsletter today to receive updates on the latest news, tutorials and special offers!

Loading

Related Posts

ArrowRight-green-icon