Dan Anderson
Dan Anderson

Reputation: 1120

Why is the Kotlin Synthetic is Null unless I use an explicit scope

So I have a bit of code here that used to work 1 month ago.

profile_clickable.throttleClicks {
  logger.logEvent(PageTags.MENU_PROFILE_NAV)
  edit_picture_button.visibility = View.GONE
  ProfileActivity.start(this@HomeMenuActivity, avatar.transition(), username.transition())
}

This code now fails with an NPE on edit_picture_button, avatar, and username which are all Kotlin synthetics.

When I add an explicit call to each of those items (see below) suddenly it works.

profile_clickable.throttleClicks {
  logger.logEvent(PageTags.MENU_PROFILE_NAV)
  [email protected]_picture_button.visibility = View.GONE
  ProfileActivity.start(this@HomeMenuActivity, [email protected](), [email protected]())
}

throttleClicks is an extension method that does this:

fun View.throttleClicks(
  windowDurationMs: Long = 800,
  onClick: View.() -> Unit
) {
  setOnClickListener(object : View.OnClickListener {

    // Set lastClickTime to - windowDurationMs to ensure the first click won't be throttled.
    var lastClickTime = -windowDurationMs

    override fun onClick(v: View?) {
      val time = SystemClock.elapsedRealtime()
      if (time - lastClickTime >= windowDurationMs) {
        lastClickTime = time
        onClick()
      }
    }
  })
}

Why do I suddenly have to use an explicit scope to avoid NPEs?

Upvotes: 2

Views: 91

Answers (1)

Mykhailo Plotnikov
Mykhailo Plotnikov

Reputation: 108

Because you use synthetics in functiun of type View.() -> Unit.

So this in function is view on whitch you apply this function (profile_clickable).

Kotlin synthetics works like

val View.profile_clickable: ImageView get() {
  if (cache exists) {
    return cache
  }
  return this.findViewById(R.id.profile_clickable)
}

profile_clickable hasn't any childs, so there will be exception.

You can use this code:

profile_clickable.throttleClicks {
  logger.logEvent(PageTags.MENU_PROFILE_NAV)
  [email protected] {
    edit_picture_button.visibility = View.GONE
    ProfileActivity.start(this, avatar.transition(), username.transition())
  }
}

Upvotes: 3

Related Questions