Invalid access modifier in ViewHolder


#1

Kotlin: 1.1.51-release-Studio3.0-1
Andnroid Studio: 3RC1
ButterKnife: 8.8.1
I have following code

class ChatItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    @Nullable
    @BindView(R.id.text_chat)
    public var textView: TextView? = null

    @Nullable
    @BindView(R.id.text_chat)
    lateinit var textView2: TextView

    init {
        ButterKnife.bind(this, itemView)
        textView?.let {
            TextViewCompat.setAutoSizeTextTypeWithDefaults(it, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM)
        }
    }
}

and getting
error: @BindView fields must not be private or static.
kotlin bytecode

// class version 50.0 (50)
// access flags 0x31
public final class com/ctrlgroup/pathway/main/ChatItemViewHolder extends android/support/v7/widget/RecyclerView$ViewHolder  {


  // access flags 0x2
  private Landroid/widget/TextView; textView
  @Landroid/support/annotation/Nullable;() // invisible
  @Lbutterknife/BindView;(value=2131230875) // invisible
  @Lorg/jetbrains/annotations/Nullable;() // invisible

java

@kotlin.Metadata(mv = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"...something..."}, d2 = {"Lcom/ctrlgroup/pathway/main/ChatItemViewHolder;", "Landroid/support/v7/widget/RecyclerView$ViewHolder;", "itemView", "Landroid/view/View;", "(Landroid/view/View;)V", "textView", "Landroid/widget/TextView;", "getTextView", "()Landroid/widget/TextView;", "setTextView", "(Landroid/widget/TextView;)V", "textView2", "getTextView2", "setTextView2", "app_debug"})
public final class ChatItemViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {
    @org.jetbrains.annotations.Nullable()
    @butterknife.BindView(value = 2131230875)
    @android.support.annotation.Nullable()
    private android.widget.TextView textView;
    @org.jetbrains.annotations.NotNull()
    @butterknife.BindView(value = 2131230875)
    @android.support.annotation.Nullable()
    public android.widget.TextView textView2;

Any ideas why is the textView private ? even if i explicitly set public

Regards,


#2

Kotlin does not have fields. But they are implemented as fields in Java, and those Java fields are always private. The corresponding getter and the setter have the visibility that you specify.

That is the explanation. There probably is a way to increase the visibility of the backing field, but unfortunately I do not know what that is.


#3

Hi,

ty for response.
Well I’d say the result is unexpected or at least inconsistent from my point of view.

  • var textView: TextView? = null is private field in java
  • lateinit var textView2: TextView is public field in java

I’m not sure why the null-ability has an influence for the access modifier…


#4

If it differs, it would surprise me too.


#5

I found what you are looking for @JvmField.


#6

Hi,

ty, just found that as well.
It helps for my particular case…

Still wondering what’s the reason for this behaviour, using this annotation feels like workaround instead of proper solution…


#7

It certainly is not a workaround. Kotlin targets multiple platforms, so it can only have language features that map to all these platforms.

However, if you know that you are going to deploy to a particular platform, then you can use extra capabilities to inter operate with that platform better. But this should be avoided as much as possible, and should only be used when:

  • Existing libraries on that platform have specific requirements on classes.
  • You want the Kotlin library that you write to provide a good API to the native language of the platform.