Kotlin views with synthetic binding and nullability

kotlin synthetic
kotlin view must have a tag
synthetic binding definition
kotlin synthetic example
unresolved reference: findviewbyid
settext in kotlin
findviewbyid in kotlin
typeparceler

I've noticed that when using Kotlin's synthetic binding, the view returned is non null (Kotlin will return View!). But this doesn't make much sense to me, since findCachedViewById can actually return null results, meaning that views can actually be null.

public View _$_findCachedViewById(int var1) {
  if(this._$_findViewCache == null) {
     this._$_findViewCache = new HashMap();
  }

  View var2 = (View)this._$_findViewCache.get(Integer.valueOf(var1));
  if(var2 == null) {
     View var10000 = this.getView();
     if(var10000 == null) {
        return null;
     }

     var2 = var10000.findViewById(var1);
     this._$_findViewCache.put(Integer.valueOf(var1), var2);
  }

  return var2;
}

So why are they not optional in this case? Why doesn't Kotlin simply return View? when using synthetic binding, so that developers would be forced to check nullability when dealing with views?

Maybe it's just because I'm new to Kotlin, but I think this is a bit counter intuitive, since the variable is not optional but we are still supposed to check if the View is in fact not null.

So in this case, does it make sense to do something like the code below?

view?.let {
    // handle non null view here
}

I figured it out, I always find the correct SO question right after I post mine :)

The single exclamation point following the View does not actually mean that the view can not be null like I expected.

This answer to another question essentially answers my exact question. The View, when using synthetic binding, can actually be null, but we can't know for sure, hence the single exclamation mark.

So it's safe to assume that the code I posted above - using ?.let{...} is perfectly acceptable way of dealing with views when you are not sure if they are already initialised when accessing them.

The cases where views might be null are very rare, but it can happen.

Kotlin views with synthetic binding and nullability, Kotlin views with synthetic binding and nullability. I've noticed that when using Kotlin's synthetic binding, the view returned is non null (Kotlin will return View! ). But this doesn't make much sense to me, since findCachedViewById can actually return null results, meaning that views can actually be null. Kotlin synthetic binding makes it much simpler and easier to bind views in your code. It has a easy to implement interface and is supported in Kotlin. We declare id for the components and the id is the only aspect we make use in the synthetic binding we previously seen different ways of binding data when compared to them this is much simpler and easier.

As you pointed out already, a single exclamation mark does not mean that it's not null, but rather that it's a Java platform type and the compiler doesn't know if it's nullable or not.

I think what you have suggested is fine, although it fails silently in the actual case of a null which might not actually be what you want.

Let's say you tried to call your view in onCreateView and forgot that it will not be initialised yet. The fragment will not behave as expected but it won't produce a meaningful error to help you debug the issue.

I'm still trying to settle on one solution or another myself but I would suggest either explicitly handling the case of a null:

view?.let {
    //...
} ?: throwExceptionIfDebugElseLogToCrashlytics()

Or decide that this time you actually want it to throw the NullPointerException in which case I would suggest:

view!!.let {
    //...
}

The latter doesn't bloat your code for what "should" be an impossible edge case and it doesn't fail silently, but it still makes it clear to a reader that view could be null. Obviously the !! is not needed by the compiler, it is just there to make the chosen strategy for dealing with platform types more explicit.

The Argument Over Kotlin Synthetics, A discussion over Kotlin synthetics and the reason commit message of a developer could forget that view is now nullable and leads to crashes a few other options such as Data Binding and Butter/KotterKnife that can also  It was mentioned briefly in the beginning of the article, and the main disadvantage that synthetic imports have over the new View Binding approach is nullability. This is a problem mainly in two

The idea is that xml layouts in Android are pretty static and in order to use synthetic views, you must create a direct import of the parsed layout:

import kotlinx.android.synthetic.main.activity_main.*

So there are no real-life, non-magic scenarios where the View would be null. Unless you choose the wrong synthetic layout, but then you will get the crash on first run.

That said, it will of course break if you modify the view on runtime, removing Views etc. But again, this is not the default usage for synthetic Views and requires a different approach.

Kotlin views with synthetic binding and nullability, I've noticed that when using Kotlin's synthetic binding, the view returned is non null (Kotlin will return View!). But this doesn't make much sense to me, since  They Don’t Expose Nullability. If a survey were taken of developers’ favorite features of Kotlin, null safety would be near the top. However, with synthetics, all views are declared as platform types (ex: TextView!) and the compiler has no idea if it should be null or not.

I think Kotlin synthetic properties should be nullable : androiddev, Is there any way to enforce nullability checks for synthetic properties? (view is null) is when I import a wrong layout and there is a view with the same id in I wrote about using Dagger Multibinding to initialize gradle modules at App Startup​. If you use Kotlin Android Extensions, you’ve probably heard of View Binding feature. “Say goodbye to findViewById” by Antonio Leiva is a very popular article. The obvious benefit of using View Binding by KTX is it makes your code more concise. You don’t have to use findViewById or the @BindView annotation of ButterKnife library.

Pros/cons of Android view access strategies, Kotlin Android Extensions' synthetic view properties allows for null access before view inflation whereas Data Binding library exposes view  Kotlin's type system is aimed at eliminating the danger of null references from code, also known as the The Billion Dollar Mistake. One of the most common pitfalls in many programming languages, including Java, is that accessing a member of a null reference will result in a null reference exception. In Java this would be the equivalent of a NullPointerException or NPE for short.

Kotlin Android Extensions: Say goodbye to findViewById (KAD 04), You'll learn how you can work with views with Kotlin Android Extensions in a much easier way, import kotlinx.android.synthetic.main.activity_main. null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { init ViewHolder​(containerView), LayoutContainer { fun bind(title: String) { itemTitle.text = "Hello Kotlin! Kotlin Android Extensions are another Kotlin plugin that is included in the regular one, and that will allow recovering views from Activities, Fragments, and Views in an amazing seamless way. The plugin will generate some extra code that will allow you to access views in the layout XML, just as if they were properties with the name of the id

Comments
  • Whats the case with recyclerview then?
  • Well, one real life scenario where View can be null is if you create a new Fragment and then call a view in that fragment before onCreateView method is executed.
  • Sure, but this is a problem with findViewById as well, so the programmer is kinda expected to realise this ^^
  • Thanks for your answer, you are technically correct, but I don't think it's the right answer to my question. I figured it out by finding another similar SO question where the answer is exactly what I expected. Take a look :) I posted an answer to my question.