尝试在空对象引用上调用接口方法“java.lang.Object kotlin.Lazy.getValue()”

Cyr*_*rus 15 android kotlin

抱歉我的愚蠢问题。

我有谷歌这个问题,但答案对我不起作用。

这是我的代码。

  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!!
        }

    }
Run Code Online (Sandbox Code Playgroud)

当我尝试获取formatDateString价值时,会发生上述异常。

代码访问formatDateString如下

  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)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我认为这个异常是由 Gson 引起的,但我不知道为什么

And*_*ana 12

我不是专业人士,但我想告诉你我发现了什么。让我们创建一个简单的类来看看 Kotlin 中的委托是如何工作的。以防万一,我正在使用 Kotlin 1.3.70。这是我们的简单类:

class Test {
    val test by lazy { "test" }
}
Run Code Online (Sandbox Code Playgroud)

在 Idea 或 Android Studio 中,您可以检查字节码。但至少对我来说,阅读 JVM 字节码非常困难:) 让我们将其转换为类似于 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);
   }
}
...
Run Code Online (Sandbox Code Playgroud)

如您所见,Kotlin 为lazy委托创建了一个特殊字段,该字段在构造函数中初始化。问题是 Gson 使用UnsafeAllocator并且不调用构造函数。你可以在这里阅读更多关于它的信息。因此,当您反序列化您的Article对象时,它包含null而不是适当的lazy委托。这就是为什么在尝试调用此 del 时会出现空指针异常的原因

  • 作为快速解决方案,您可以编写扩展函数。但如果您要频繁调用“formatDateString”,则会产生一些开销。另外,您可以使用其中包含“formatDateString”的包装器。但使用起来不会很方便。也许你可以考虑从 Gson 迁移到 Moshi 或 kotlinx.serialization,但这是一个相当大的工作量 (2认同)