Writing Android views in Kotlin


#1

I'm trying to use Kotlin for developing Android applications. Unfortunately, I found out that either it's impossible to write Android views in Kotlin or I maybe just miss something.

Android views may have up to three default constructors which are usually chained:

public class MyView extends View {
  public MyView(Context context) {
  this(context, null);
  }
  
  public MyView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
  }


  public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  }
}

The first one is usually used for instantiating a view from code, while two others are called when instantiating a view from its XML representation. More precisely, the second constructor is called by Android via reflection and third one is called by subclasses in order to provide a default style for the view. Currently Kotlin supports only primary constructors so you cannot make the view with overridable default style. Not only is it iconvenient, but it also makes some views impossible to implement correctly, that is when you want to make the base view class customizable via a style attribute.

And the second problem is related not to Kotlin itself but to the compiler. As you can see from the java code above, AttributeSet is a nullable parameter. But the Kotlin compile thinks it’s not and gives me the following error:

class MyView(context: Context, attrs: AttributeSet?) : View(context, attrs) {}

MyView.kt:34:None of the following functions can be called with the arguments supplied:
public constructor View(context: android.content.Context) defined in android.view.View
public constructor View(context: android.content.Context, attrs: android.util.AttributeSet) defined in android.view.View
public constructor View(context: android.content.Context, attrs: android.util.AttributeSet, defStyle: kotlin.Int) defined in android.view.View

In this SO post Andrey Breslav offers to pass an empty instance of AttributeSet to the super constructor, but AttributeSet is an interface with 22 methods, not a class. Of cource I can create an empty Proxy implementation of this interface but I’m not sure that it will work on all Android versions and their modifications, and I don’t want to check.

I believe that Kotlin is a great language and it can make life of Android developers easier as it’s more expressive and less verbose than Java and at the same time easier to use (in my opinion) and more lightweight than Scala. But such fundamental problems make this language not very convenient to use in Android development. So I hope these problems can be fixed somehow and I will be very glad when it happens.


#2

What I usually do is to leave implementation in Java if things get hairy like this since you can just mix and match Kotlin and Java code in the same Android project. There may be an elegant Kotlin solution to this. Let me spike this out this weekend.


#3

That's how I solved the problem but I believe that the purpose of Kotlin is to substitute Java and not to complement it. So in my opinion it must be possible to implement such pretty simple stuff in pure Kotlin.