对不起我的愚蠢问题。
我有Google这个问题,但答案对我来说不起作用。
这是我的代码。
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!!
}
}
当我尝试获取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)
}
}
}
我认为此异常是由Gson引起的,但我不知道为什么
答案 0 :(得分:7)
我不是专业人士,但我想告诉您我所发现的内容。让我们创建一个简单的类,看看Kotlin中的委托如何工作。以防万一,我正在使用Kotlin 1.3.70
。这是我们的简单类:
class Test {
val test by lazy { "test" }
}
在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);
}
}
...
如您所见,Kotlin为lazy
委托创建了一个特殊字段,该字段在构造函数中初始化。问题是Gson使用UnsafeAllocator并且没有调用构造函数。您可以阅读有关它的更多信息,例如here。因此,在反序列化Article
对象时,它包含null
而不是适当的lazy
委托。这就是为什么在尝试调用此del时出现空指针异常的原因
答案 1 :(得分:0)
当尝试在数据内部写入方法时,我也遇到了异常“ java.lang.NullPointerException:尝试在空对象引用上调用接口方法'java.lang.Object kotlin.Lazy.getValue()'”类(针对Gson)。
data class SomeResponse(
override val success: Int,
override val errors: ErrorsResponse?
) {
data class ErrorsResponse(
@SerializedName("id")
val id: Int?
) {
private val errorUtil by lazy { ErrorUtil() }
fun getErrorMessage(): String? =
errorUtil.getErrorMessage(id)
}
}
无论是errorUtil by lazy { ErrorUtil() }
还是errorUtil = ErrorUtil()
,当我们呼叫null
时都是getErrorMessage
。它不会很快被初始化。
要解决此问题,请在调用时初始化变量。
private var errorUtil: ErrorUtil? = null
fun getErrorMessage(): String? {
if (errorUtil == null) errorUtil = ErrorUtil()
return errorUtil!!.getErrorMessage(id)
}