2

I have next data class in my app:

data class CarouselItem(
val url: String,
val pictureId: String,
val visible: String,
val id : String = UUID.randomUUID().toString()
) 

I get from the backend list of CarouselItems. They contain the first 3 fields (url, pictureId and visible). I want to additionally add field id to all created objects and add random unique id value to them. (would like to avoid wrapping this class with another one)

I expected this code to work, but instead, the id is not generated. I also tried adding it like this:

    data class CarouselItem(
    val url: String,
    val pictureId: String,
    val visible: String
) {
    val id: String = UUID.randomUUID().toString()
}

but it did not help. The id field is still null. To solve this, I added in the code for loop to go through the list and add these values.

I am curious, why is this not working. And is there any way to add these values in the data class? It looks much cleaner like that IMO. Thanks

4
  • 2
    "I get from the backend list of CarouselItems" -- we would need to see your code for doing this. Bear in mind that default values are not necessarily used, particularly if the object is being created by a Java library via reflection. That is fairly typical for things like Retrofit adapters (e.g., the Gson adapter). Commented Jan 20, 2022 at 15:46
  • @CommonsWare I use DI and coroutines so code extends itself in multiple classes. Indeed I use retrofit library for the API call so I understand your point. You want to say that in this case (while using retrofit), this is not possible? Commented Jan 20, 2022 at 16:18
  • Are you using a serialisation library with Retrofit, ie Moshi? Commented Jan 21, 2022 at 8:02
  • @ScottCooper we use Gson for serialization Commented Jan 21, 2022 at 8:11

4 Answers 4

2

CommonsWare is correct in that Gson creates your objects via reflection which is why these default values aren't being assigned. Moshi is another adapter that supports this feature but it might be a big job to switch retrofit adapters.

Since this id field isn't actually used in serialization this might work as a quick alternative

data class CarouselItem(
    val url: String,
    val pictureId: String,
    val visible: String
) {
    val id: String by lazy { UUID.randomUUID().toString() }
}

Lazy values aren't assigned until they're called first time, any subsequent calls return the same value so the id will remain the same.

Sign up to request clarification or add additional context in comments.

Comments

1

You will often find occasions when you need to add, remove, manipulate fields in items you get from an api in order to make them fit the needs of an app. I find that it helps to have different classes to represent local and API data. That way you can make changes to one without necessarily affecting the other.

Using this approach you could have 2 data classes

data class ApiCarouselItem(
val url: String,
val pictureId: String,
val visible: String)

data class LocalCarouselItem(
val id: String,
val url: String,
val pictureId: String,
val visible: String)

The when you receive your api data it's a simple task to map from one to the other

val apiItems = // list of your items from the api
val localItems = apiItems.map{ apiItem -> 
    LocalApiItem(
    id = UUID.randomUUID().toString(),
    // assign url, pictureId, visible
    )    
}

Comments

0

Using the map function, transform each CarouselItem object to a new one with the generated id, by using the copy() function inate to data classes:

carouselItems.map { it.copy(id = UUID.randomUUID().toString()) }

If you want to name the parameter:

carouselItems.map { carouselItem -> carouselItem.copy(id = UUID.randomUUID().toString()) }

1 Comment

Well it's weird but this code doesn"t work. I debugged and my id parameter is null. So I had to revert back to my current code: for (element in value) { element.id = UUID.randomUUID().toString() } carouselItems.postValue(value)
0

I know it's old , but here is how i do it in case anyone in need

    data class CarouselItem(
        
        val string1: String = "",
        val string2: String = "",
        val string3: String = ""
    ) {
      var id: String= "1"
      fun addExtraFields() :CarouselItem{
          id = UUID.randomUUID().toString()
          return this
       }
}

and when creating new object

var carouse=CarouselItem("info1","info2","info3").addExtraFields()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.