Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attempt to invoke interface method 'java.lang.Object kotlin.Lazy.getValue()' on a null object reference

Tags:

android

kotlin

Sorry for my stupid question.

I have Google this problem, but the answer couldn't work for me.

This is my code.

  data class Article(val id: Long, val title: String, val ingress: String, val image: String,
                       val dateTime: String, val tags: List<String>, val content: List<Item>, val created: Long, val changed: Long) {

        @delegate:Transient
        val formatDateString: String by lazy {
            val sdf = SimpleDateFormat("dd.MM.yyyy HH.mm")
            val date: Date = sdf.parse(dateTime)
            var time: String?
            if (date.year == Date().year) {
                time = SimpleDateFormat("dd MM,HH:mm", Locale.US).format(date)
            } else {
                time = SimpleDateFormat("dd MM yyyy,HH:mm", Locale.US).format(date)
            }
            time!!
        }

    }

when i try to get formatDateString value , Above exception will happen.

The codes access formatDateString as following

  override fun getCustomAdapter(): BaseQuickAdapter<CarListResponseBody.Article, BaseViewHolder> {
        return object : BaseQuickAdapter<CarListResponseBody.Article, BaseViewHolder>( R.layout.app_item_cars_list,dataList) {
            override fun convert(helper: BaseViewHolder, item: CarListResponseBody.Article) {
                helper.setText(R.id.tv_ingress,item.ingress)
                helper.setText(R.id.tv_date_time,item.formatDateString)
                helper.setText(R.id.tv_title,item.title)
                ImageLoadUtil.loadImgToView(context,item.image,helper.getView(R.id.img_car),null)
            }
        }
    }

I think this exception caused by Gson, But i have no idea why

like image 676
Cyrus Avatar asked May 05 '19 12:05

Cyrus


2 Answers

I'm not a pro but I'd like to tell you what I've found. Let's create a simple class to see how delegates in Kotlin work. Just in case, I'm using Kotlin 1.3.70. Here is our simple class:

class Test {
    val test by lazy { "test" }
}

In the Idea or Android Studio, you can check the bytecode. But it's pretty hard to read JVM bytecode at least for me :) Let's convert it to something looks like Java:

...
public final class Test {
   @NotNull
   private final Lazy test$delegate;

   @NotNull
   public final String getTest() {
      Lazy var1 = this.test$delegate;
      Object var3 = null;
      boolean var4 = false;
      return (String)var1.getValue();
   }

   public Test() {
      this.test$delegate = LazyKt.lazy((Function0)null.INSTANCE);
   }
}
...

As you see Kotlin creates a special field for lazy delegate which initializes in the constructor. The problem is Gson uses UnsafeAllocator and doesn't call the constructor. You can read a bit more about it for example here. So when you deserialize your Article object it contains null instead of appropriate lazy delegate. That's why you got a null pointer exception when trying to call this del

like image 104
Andrei Tanana Avatar answered Nov 19 '22 16:11

Andrei Tanana


I ran into the same problem when using properties not filled by Gson. I used the following work around

var myString: String? = null
    get() {
        if (field == null) {
            field = "myInitialValue"
        }
        return field
    }

which I guess would be this then in your example:

val formatDateString: String? = null
    get() {
        if (field == null) {
            val sdf = SimpleDateFormat("dd.MM.yyyy HH.mm")
            val date: Date = sdf.parse(dateTime)
            var time: String?
            if (date.year == Date().year) {
                time = SimpleDateFormat("dd MM,HH:mm", Locale.US).format(date)
            } else {
                time = SimpleDateFormat("dd MM yyyy,HH:mm", Locale.US).format(date)
            }
            field = time!!
        }
        return field
    }
        

I have no idea if it's bad practice but it seems to do the job for me

like image 34
Ivo Beckers Avatar answered Nov 19 '22 14:11

Ivo Beckers