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
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With