Kotlin android extension

这篇发出去了,medium里


Every new created Android Kotlin project has apply plugin: 'kotlin-android-extensions' by defaul in the app build.gradle file.

Happy beginning

With it, we don’t have to write .findViewById(<id>) to get a view that we need.

Instead, we have something like this:

import kotlinx.android.synthetic.main.main_fragment.*

Then we can use any view underneath by using view id directly.

property_list.apply {
    layoutManager = LinearLayoutManager(it)
    adapter = CardsAdapter(list) { param -> clickHandler(param) }
}

property_list is the RecyclerView id in the layout.xml file.

So far so good

As long as you use this feature in Activity or Fragment, it looks good. And it IS good. Since kotlin-android-extensions ‘s view memoization strategy - cache the result of .findViewById() in a HashMap and provide _$_findCachedViewById to fetch the view we retreived before.

Here is how I am aware of this:

  1. Show Kotlin Bytecode
  2. Decompile

What about other places

Normal it is in ViewHolder. But since we already reduced the binding behaviour by using tag to save data object. We can avoid multi-binding, so there is no benefic if we cache view in ViewHolder.

If data in ViewHolder is changing all the time you need to re-bind. Then we can make ViewHolder to take advantage of Kotlin extesion to save energy by using cached view.

But in our project, we use an app architechture MVP++ – we have a view mediator, which manipulate all the view access and value / visibility / color setting. This mediator class is a normal class have a view in the constructor. Like this:

class SomeViewMediator(private val view: View) {...}

When I decompiled the Kotlin Bytecode, found that .findViewById() is used other than .findCachedViewById(). That means every time we access view, it goes to .findViewById().

hmm…a bit expensive.

Change

LayoutContainer and replease

import kotlinx.android.synthetic.main.main_fragment.view.*

to

import kotlinx.android.synthetic.main.main_fragment.*

And then decouple the generated Kotlin code, we can see findCachedViewById is used everywhere when we need to access a view. And .findViewById() is only used at the first time getting a view of entire hierachy.

That’s it.