Parse JSON list to object Kotlin Retrofit and Moshi - kotlin

Hi I'm use Kotlin retrofit and moshi
I have that JSON
[
{
"id": "bitcoin",
"symbol": "btc",
"name": "Bitcoin",
"image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
"current_price": 21917,
"market_cap": 418101666154,
"market_cap_rank": 1,
"fully_diluted_valuation": 459616529150,
"total_volume": 35275748678,
"high_24h": 22967,
"low_24h": 21800,
"price_change_24h": -785.2614865719079,
"price_change_percentage_24h": -3.4589,
"market_cap_change_24h": -16487597586.019958,
"market_cap_change_percentage_24h": -3.79383,
"circulating_supply": 19103175,
"total_supply": 21000000,
"max_supply": 21000000,
"ath": 69045,
"ath_change_percentage": -68.28207,
"ath_date": "2021-11-10T14:24:11.849Z",
"atl": 67.81,
"atl_change_percentage": 32195.96528,
"atl_date": "2013-07-06T00:00:00.000Z",
"roi": null,
"last_updated": "2022-07-25T18:38:56.019Z"
},
{
"id": "ethereum",
"symbol": "eth",
"name": "Ethereum",
"image": "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
"current_price": 1522.52,
"market_cap": 181649214301,
"market_cap_rank": 2,
"fully_diluted_valuation": null,
"total_volume": 17695232530,
"high_24h": 1651.4,
"low_24h": 1510.24,
"price_change_24h": -72.84932292922076,
"price_change_percentage_24h": -4.56629,
"market_cap_change_24h": -10281152619.016693,
"market_cap_change_percentage_24h": -5.35671,
"circulating_supply": 119829051.14353,
"total_supply": 119829051.14353,
"max_supply": null,
"ath": 4878.26,
"ath_change_percentage": -68.9122,
"ath_date": "2021-11-10T14:24:19.604Z",
"atl": 0.432979,
"atl_change_percentage": 350158.16453,
"atl_date": "2015-10-20T00:00:00.000Z",
"roi": {
"times": 91.78338127800683,
"currency": "btc",
"percentage": 9178.338127800684
},
"last_updated": "2022-07-25T18:39:03.483Z"
},
{
"id": "tether",
"symbol": "usdt",
"name": "Tether",
"image": "https://assets.coingecko.com/coins/images/325/large/Tether-logo.png?1598003707",
"current_price": 1.001,
"market_cap": 65934603930,
"market_cap_rank": 3,
"fully_diluted_valuation": null,
"total_volume": 49334676401,
"high_24h": 1.011,
"low_24h": 0.996453,
"price_change_24h": 0.00015041,
"price_change_percentage_24h": 0.01503,
"market_cap_change_24h": 33333966,
"market_cap_change_percentage_24h": 0.05058,
"circulating_supply": 65876317670.4762,
"total_supply": 65876317670.4762,
"max_supply": null,
"ath": 1.32,
"ath_change_percentage": -24.34669,
"ath_date": "2018-07-24T00:00:00.000Z",
"atl": 0.572521,
"atl_change_percentage": 74.83471,
"atl_date": "2015-03-02T00:00:00.000Z",
"roi": null,
"last_updated": "2022-07-25T18:36:04.706Z"
}
]
So I make a 2 classes
data class TopCrypto(
val cryptos: List<CryptoStock>? = null
)
and
data class CryptoStock(
val id: String? = null,
val symbol: String? = null,
val image: String? = null,
val currentPrice: String? = null,
val priceChange: Double? = null
)
i try use Call<List> but it's not what i want.
I'd like to have respons in TopCrypto
interface CryptoService {
#GET("coins/markets")
fun getTopCrypto(#Query("vs_currency") vsCurrency:String,
#Query("per_page") limit: Int,
#Query("order") order:String = "market_cap_desc"
): Call<TopCrypto>
}
object
object Api {
private val BASE_URL = "https://api.coingecko.com/api/v3/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
val retrofitService: CryptoService by lazy{
retrofit.create(CryptoService::class.java)
}
}
class CryptoManager {
init {
getCryptos()
}
private val _cryptoResponse = mutableStateOf(TopCrypto())
val cryptoResponse: State<TopCrypto>
#Composable get() = remember {
_cryptoResponse
}
private fun getCryptos(){
val service = Api.retrofitService.getTopCrypto("usd",10)
service.enqueue(object : Callback<TopCrypto> {
override fun onResponse(call: Call<TopCrypto>, response: Response<TopCrypto>) {
if (response.isSuccessful){
_cryptoResponse.value = response.body()!!
Log.d("crypto","${_cryptoResponse.value}")
}else{
Log.d("error","${response.errorBody()}")
}
}
override fun onFailure(call: Call<TopCrypto>, t: Throwable) {
Log.d("error","${t.message}")
}
})
}
}
For now i have Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $.
I know i must map somehow Json array to my class TopCrypto
Thanks in advance for help :)

I do like Eric and Jorn said :). Remove class TopCrypto and change
CryptoManager class
class CryptoManager {
init {
getCryptos()
}
private val _cryptoResponse = mutableStateOf(CryptoStock())
val cryptoResponse: MutableState<CryptoStock>
#Composable get() = remember {
_cryptoResponse
}
private fun getCryptos(){
val service = Api.retrofitService.getTopCrypto("usd",5)
service.enqueue(object : Callback<List<CryptoStock>>
{
override fun onResponse(call: Call<List<CryptoStock>>, response: Response<List<CryptoStock>>) {
if (response.isSuccessful){
Log.d("apiHeaders","${response.headers()}")
Log.d("apiBody","${response.body()}")
}else{
Log.d("error","${response.errorBody()}")
}
}
override fun onFailure(call: Call<List<CryptoStock>>, t: Throwable) {
Log.e("TAG", "login() - onFailure() ", t)
}
})
}
and inteface
interface CryptoService {
#GET("coins/markets")
fun getTopCrypto(#Query("vs_currency") vsCurrency:String,
#Query("per_page") limit: Int,
#Query("order") order:String = "market_cap_desc"
): Call<List<CryptoStock>>
}

Problem is in creating data class from JSON string.
Your data class TopCrypto requires object but response json string has list so I have tried to modify data class, Can you please try below data class once
class TopCrypto : ArrayList<TopCrypto.TopCryptoData>(){
data class TopCryptoData(
val ath: Double,
val ath_change_percentage: Double,
val ath_date: String,
val atl: Double,
val atl_change_percentage: Double,
val atl_date: String,
val circulating_supply: Double,
val current_price: Double,
val fully_diluted_valuation: Long,
val high_24h: Double,
val id: String,
val image: String,
val last_updated: String,
val low_24h: Double,
val market_cap: Long,
val market_cap_change_24h: Double,
val market_cap_change_percentage_24h: Double,
val market_cap_rank: Int,
val max_supply: Int,
val name: String,
val price_change_24h: Double,
val price_change_percentage_24h: Double,
val roi: Roi,
val symbol: String,
val total_supply: Double,
val total_volume: Long
) {
data class Roi(
val currency: String,
val percentage: Double,
val times: Double
)
}
}

Related

I want to receive as a json array instead of a json object in Kotlin retrofit

data class LeagueEntryDTO(
#SerializedName("leagueId") val leagueId : String,
#SerializedName("summonerId") val summonerId : String,
#SerializedName("summonerName") val summonerName : String,
#SerializedName("queueType") val queueType : String,
#SerializedName("tier") val tier : String,
#SerializedName("rank") val rank : String,
#SerializedName("leaguePoints") val leaguePoints : Int,
#SerializedName("wins") val wins : Int,
#SerializedName("losses") val losses : Int,
#SerializedName("hotStreak") val hotStreak : Boolean,
#SerializedName("veteran") val veteran : Boolean,
#SerializedName("freshBlood") val freshBlood : Boolean,
#SerializedName("inactive") val inactive : Boolean,
#SerializedName("miniSeries") val miniSeries : MiniSeriesDTO
)
private fun searchLeagueEntryByEncryptedSummonerId(id: String){
lolAPI.getSummonerEntriesByEncryptedSummonerID(id, API_KEY)
.enqueue(object : Callback<LeagueEntryDTO>{
override fun onResponse(
call: Call<LeagueEntryDTO>,
response: Response<LeagueEntryDTO>
) {
if(response.isSuccessful.not()){
Log.e("MainActivity", "${response.code()}")
return
}
response.body()?.let {
Log.e("MainActivity", it.toString())
Log.e("MainActivity", "${response.code()}")
}
}
override fun onFailure(call: Call<LeagueEntryDTO>, t: Throwable) {
Log.e("MainActivity", "${call.request().url()}")
Log.e("MainActivity", "${t.cause}")
call.request().body().let {
Log.e("MainActivity", "${it.toString()}")
}
}
})
}
#GET("/lol/league/v4/entries/by-summoner/{encryptedSummonerId}")
fun getSummonerEntriesByEncryptedSummonerID(
#Path("encryptedSummonerId") encryptedSummonerId : String,
#Query("api_key") APIKey : String
): Call<LeagueEntryDTO>
data to receive
[
{
"leagueId": "e04db760-931c-475f-88b8-b94979f013da",
"queueType": "RANKED_SOLO_5x5",
"tier": "GOLD",
"rank": "III",
"summonerId": "fhXsvqx4tjuqt7JWGeTMUuMihXlqNwDIsPHEWwc3urIBtCc",
"summonerName": "do skip leg day",
"leaguePoints": 23,
"wins": 62,
"losses": 72,
"veteran": false,
"inactive": false,
"freshBlood": false,
"hotStreak": false
}
]
But the format of the data I am receiving in my code
{
"leagueId": "e04db760-931c-475f-88b8-b94979f013da",
"queueType": "RANKED_SOLO_5x5",
"tier": "GOLD",
"rank": "III",
"summonerId": "fhXsvqx4tjuqt7JWGeTMUuMihXlqNwDIsPHEWwc3urIBtCc",
"summonerName": "do skip leg day",
"leaguePoints": 23,
"wins": 62,
"losses": 72,
"veteran": false,
"inactive": false,
"freshBlood": false,
"hotStreak": false
}
error caused by it
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
How to solve this problem?
I am trying to use Retrofit using Riot Open API.
Help
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
So you should be expecting to receive List<LeagueEntryDTO>
Replace Call<LeagueEntryDTO> with Call<List<LeagueEntryDTO>>, as well in other places

How to serialize/deserialize json with nested field in kotlin?

I am using Json.decodeFromString<User>("json string") (https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md)
model is like
data class User(val id: String, val name: String, val assets: List<Asset>)
data class Asset(val id: String, val sku: String, val name: String)
but input json is like
{
"data": {
"id": "userId",
"name": "userName",
"body": {
"assets": [
{
"data": {
"id": "assetId",
"sku": "assetSku",
"name": "assetName"
}
}
]
}
}
}
How can I parse json with serializer? Seems not able to parse with delegate and surrogate serializers easily.
Your POJO seems to be wrong , every field needs to have name corresponding to json value , or use GSON's SerializedName annotation and Parse sing Gson.
Your User POJO should look something like this,
data class User (
#SerializedName("data") var data : UserData
)
data class UserData(
#SerializedName("id") var id : String,
#SerializedName("name") var name : String,
#SerializedName("body") var body : Body
)
data class Body (
#SerializedName("assets") var assets : List<Assets>
)
data class Assets (
#SerializedName("data") var data : AssetsData
)
data class AssetsData(
#SerializedName("id") var id : String,
#SerializedName("sku") var sku : String,
#SerializedName("name") var name : String
)
for serializing and deserializing
dependencies {
implementation 'com.google.code.gson:gson:2.8.9'
}
val gson = Gson()
val jsonValue = gson.toJson(User)
val jsonToUser = gson.fromJson(jsonValue ,User::class.java)
Read about https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#under-the-hood-experimental
Tried something like this:
#Serializable(with = AssetSerializer::class)
data class Asset(val id: String, val sku: String, val name: String)
#Serializable(with = UserSerializer::class)
data class User(val id: String, val name: String, val assets: List<Asset>)
object AssetSerializer: KSerializer<Asset> {
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("Asset") {
element("data", buildClassSerialDescriptor("data") {
element("id", String.serializer().descriptor)
element("sku", String.serializer().descriptor)
element("name", String.serializer().descriptor)
})
}
override fun serialize(encoder: Encoder, value: Asset) {
require(encoder is JsonEncoder)
encoder.encodeJsonElement(buildJsonObject {
put("data", buildJsonObject {
put("id", value.id)
put("sku", value.sku)
put("name", value.name)
})
})
}
override fun deserialize(decoder: Decoder): Asset {
require(decoder is JsonDecoder)
val root = decoder.decodeJsonElement()
val element = root.jsonObject["data"]!!
return Asset(
id = element.jsonObject["id"]!!.jsonPrimitive.content,
sku = element.jsonObject["sku"]!!.jsonPrimitive.content,
name = element.jsonObject["name"]!!.jsonPrimitive.content,
)
}
}
object UserSerializer: KSerializer<User> {
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("User") {
element("data", buildClassSerialDescriptor("data") {
element("id", String.serializer().descriptor)
element("name", String.serializer().descriptor)
element("body", buildClassSerialDescriptor("body") {
element("assets", ListSerializer(Asset.serializer()).descriptor)
})
})
}
override fun serialize(encoder: Encoder, value: User) {
require(encoder is JsonEncoder)
encoder.encodeJsonElement(buildJsonObject {
put("data", buildJsonObject {
put("id", value.id)
put("name", value.name)
put("body", buildJsonObject {
put("assets", JsonArray(value.assets.map { asset ->
encoder.json.encodeToJsonElement(asset)
}))
})
})
})
}
override fun deserialize(decoder: Decoder): User {
require(decoder is JsonDecoder)
val root = decoder.decodeJsonElement()
val element = root.jsonObject["data"]!!
val assets = element
.jsonObject["body"]!!
.jsonObject["assets"]!!
.jsonArray
.map { asset ->
decoder.json.decodeFromJsonElement(asset)
}
return Asset(
id = element.jsonObject["id"]!!.jsonPrimitive.content,
name = element.jsonObject["name"]!!.jsonPrimitive.content,
assets = assets,
)
}
}

How to prevent serializing null values using kotlin serialization

I'm using kotlinx-serialization-json
I have this class:
#Serializable
data class Event(
#SerialName("temperature") val temperature: Float?,
#SerialName("pressure") val pressure: Float?,
#SerialName("humidity") val humidity: Float?,
)
and this call
Json.encodeToString(Event(temperature = 42.0f, pressure = null, humidity = 20.9f))
During serialization I receive such json:
{
"temperature": 20.5,
"pressure": null,
"humidity": 20.9
}
but I would like to prevent serializing null values and receive this:
{
"temperature": 20.5,
"humidity": 20.9
}
It's a problem for me, because during serializing lengthy list of events I waste a lot of lines. Anyone's got an idea how to achieve this?
EDIT:
There is new simple way to achieve this:
https://blog.jetbrains.com/kotlin/2021/09/kotlinx-serialization-1-3-released/#excluding-nulls
You can ignore all defaults and do something like this:
#Serializable
data class Event(
#SerialName("temperature") val temperature: Float?,
#SerialName("pressure") val pressure: Float? = null,
#SerialName("humidity") val humidity: Float?,
)
val jsonMapper = Json { encodeDefaults = false}
val body = jsonMapper.encodeToString(Event(temperature = 42.0f,pressure = null, humidity = 20.9f))
Please, be aware of that, in the above case you are ignoring ALL defaults.
If you want to ignore only null values you have to implement a custom serializer.
For this example custom serializer will look like this:
object EventSerializer: KSerializer<Event> {
override fun deserialize(decoder: Decoder): Event {
decoder.decodeStructure(descriptor) {
var temperature: Float? = null
var humidity:Float? = null
var pressure: Float? = null
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> temperature = decodeFloatElement(descriptor, 0)
1 -> pressure = decodeFloatElement(descriptor, 1)
2 -> humidity = decodeFloatElement(descriptor, 2)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
return Event(temperature, pressure, humidity)
}
}
override fun serialize(encoder: Encoder, value: Event) {
encoder.beginStructure(descriptor).run {
value.temperature?.let { encodeStringElement(descriptor, 0, it.toString()) }
value.pressure?.let { encodeStringElement(descriptor, 1, it.toString()) }
value.humidity?.let { encodeStringElement(descriptor, 2, it.toString()) }
endStructure(descriptor)
}
}
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Event") {
element<String>("temperature")
element<String>("pressure")
element<String>("humidity")
}
}
To use it -> #Serializable(with = EventSerializer::class)

GSON fromJSON Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $

I am trying to convert a string to JSONArray but I am having issues.
This is my test:
class MainActivityTest {
#Test
fun checkParse(){
val loader = ClassLoader.getSystemClassLoader()
val json: String = Files.lines(
get(
loader.getResource("data.json").toURI()
)
)
.parallel()
.collect(Collectors.joining())
val main = MainActivity()
val dataParse2 = Gson().fromJson(json, JSONArray::class.java)
val gson = GsonBuilder().create()
val parse2 = gson.fromJson(json, Array<QuoteModel>::class.java).toList()
val parse1 = main.parseResponse(dataParse2)
assertEquals(parse1,parse2)
}
}
This is the function I am testing in my MainActivity:
fun parseResponse(response: JSONArray): List<QuoteModel> {
val fileData = response.toString()
val gson = GsonBuilder().create()
return gson.fromJson(fileData, Array<QuoteModel>::class.java).toList()
}
And this is my data.json file:
[
{
"text": "Genius is one percent inspiration and ninety-nine percent perspiration.",
"author": "Thomas Edison"
},
{
"text": "You can observe a lot just by watching.",
"author": "Yogi Berra"
},
{
"text": "A house divided against itself cannot stand.",
"author": "Abraham Lincoln"
}
]
the issue comes in this line from my test:
val dataParse2 = Gson().fromJson(json, JSONArray::class.java)
Any ideas?
First Update
This is the function where I call the parseFunction in MainActivity:
private fun jsonArrayRequest(url: String): JsonArrayRequest {
return JsonArrayRequest(Request.Method.GET, url, null,
{ response ->
val quotesArray = parseResponse(response)
displayQuote(chooseQuote(quotesArray))
},
{ error ->
TODO("Handle error missing")
}
)
}
private fun jsonArrayRequest(url: String): JsonArrayRequest {
return JsonArrayRequest(Request.Method.GET, url, null,
{ response ->
val responseArray = JSONArray(response)
val quotesArray = parseResponse(responseArray)
displayQuote(chooseQuote(quotesArray))
},
{ error ->
TODO("Handle error missing")
}
)
fun parseResponse(response: JSONArray): List<QuoteModel> {
return Gson().fromJson(response.toString(), Array<QuoteModel>::class.java).toList()

How can I access the list from API to display data? (Kotlin)

I have a List of cars that I am trying to display. The data needed is from postman and to access the car info I need to first access the list but I'm not sure how to do so. I'm also not sure how to call the car function I made, Ive searched for ways but no has worked.
here is how the data in postman looks:
{
"listCar": [
{
"id": 204,
"adTitle": "AdTitlecar",
"adDate": "2019-11-07T11:52:40.0156875",
"adPrice": 25.0,
"category": "4X4",
"categoryId": 7,
"status": 1,
"brandId": 1,
"brand": "مرسيدس",
"brandModelId": 6,
"brandModel": "M300",
"kilometer": 300.0,
"modelYearId": 2,
"modelYear": "2010",
"fuelType": "بنزين",
"carFeatureFuelId": 3,
"gearType": "اوتوماتك",
"carFeatureGearId": 2,
"image": null,
"vendorId": 1
},
{
"id": 203,
"adTitle": "AdTitlecar",
"adDate": "2019-11-07T11:52:37.7771547",
"adPrice": 25.0,
"category": "4X4",
"categoryId": 7,
"status": 1,
"brandId": 1,
"brand": "مرسيدس",
"brandModelId": 6,
"brandModel": "M300",
"kilometer": 300.0,
"modelYearId": 2,
"modelYear": "2010",
"fuelType": "بنزين",
"carFeatureFuelId": 3,
"gearType": "اوتوماتك",
"carFeatureGearId": 2,
"image": null,
"vendorId": 1
},
{
"id": 202,
"adTitle": "AdTitlecar",
"adDate": "2019-11-07T11:52:35.5569602",
"adPrice": 25.0,
"category": "4X4",
"categoryId": 7,
"status": 1,
"brandId": 1,
"brand": "مرسيدس",
"brandModelId": 6,
"brandModel": "M300",
"kilometer": 300.0,
"modelYearId": 2,
"modelYear": "2010",
"fuelType": "بنزين",
"carFeatureFuelId": 3,
"gearType": "اوتوماتك",
"carFeatureGearId": 2,
"image": null,
"vendorId": 1
},
],
}
Here is my car Object I made:
object CarsListData {
var id = 0
var title = ""
var date = ""
var price = 0.0
var category = ""
var brand = ""
var model = ""
var distance = 0.0
var year = ""
var fuel = ""
var gear = ""
}
here is how im fetching the data as GET:
fun carsList(context: Context, complete: (Boolean) -> Unit) {
val carList = object : JsonObjectRequest(Method.GET, URL_CAR_LIST, null, Response.Listener { response ->
try {
CarsListData.id = response.getInt("id")
CarsListData.title = response.getString("adTitle")
CarsListData.date = response.getString("adDate")
CarsListData.price = response.getDouble("adPrice")
CarsListData.category = response.getString("category")
CarsListData.brand = response.getString("brand")
CarsListData.model = response.getString("brandModel")
CarsListData.distance = response.getDouble("kilometer")
CarsListData.year = response.getString("modelYear")
CarsListData.fuel = response.getString("fuelType")
CarsListData.gear = response.getString("gearType")
// UserDataService.image = response.getString("image")
val userDataChange = Intent(BROADCAST_USER_DATA_CHANGE)
LocalBroadcastManager.getInstance(context).sendBroadcast(userDataChange)
complete(true)
} catch (e: JSONException) {
Log.d("JSON", "EXC" + e.localizedMessage)
}
}, Response.ErrorListener {error ->
Log.d("ERROR", "Could not login user: $error")
complete(false)
}) {
override fun getBodyContentType(): String {
return "application/json; charset=utf-8"
}
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers.put("Authorization", "Bearer $authToken")
return headers
}
}
Volley.newRequestQueue(context).add(carList)
}
here is how Im broadcasting the data in the listCarPage:
LocalBroadcastManager.getInstance(this).registerReceiver(userDataChangeReciever,
IntentFilter(BROADCAST_USER_DATA_CHANGE)
)
}
private val userDataChangeReciever = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
carDetailsDate.text = CarsListData.date
carDetailsTitle.text = CarsListData.title
carDetailsCategory.text = CarsListData.category
carDetailsPrice.text = CarsListData.price.toString()
carDetailsDistance.text = CarsListData.distance.toString()
cardetailsGear.text = CarsListData.gear
carDetailsOil.text = CarsListData.fuel
carDetailsYear.text = CarsListData.year
}
}
I tried accessing the "listCar" and nothing seems to work and I just dont feel like im doing this the right way so would appreciate any suggestions!
Edit-
CarAdapter code:
class CarAdapter(context: Context, cars: List<Cars>) : BaseAdapter() {
val context = context
val cars = cars
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val carsView: View
carsView = LayoutInflater.from(context).inflate(R.layout.cars_list, null)
val carImage: ImageView = carsView.findViewById(R.id.carDetailsImage)
val carTitle: TextView = carsView.findViewById(R.id.carDetailsTitle)
val carCategory: TextView = carsView.findViewById(R.id.carDetailsCategory)
val carPrice: TextView = carsView.findViewById(R.id.carDetailsPrice)
val carDistance: TextView = carsView.findViewById(R.id.carDetailsDistance)
val carDate: TextView = carsView.findViewById(R.id.carDetailsDate)
val carGear: TextView = carsView.findViewById(R.id.cardetailsGear)
val carYear: TextView = carsView.findViewById(R.id.carDetailsYear)
val carOil: TextView = carsView.findViewById(R.id.carDetailsOil)
val car = cars[position]
carTitle.text = car.title
carCategory.text = car.category
carPrice.text = car.price
carDistance.text = car.distance
carDate.text = car.date
carGear.text = car.gear
carYear.text = car.year
carOil.text = car.oil
val resourceId = context.resources.getIdentifier(car.image, "drawable", context.packageName)
carImage.setImageResource(resourceId)
return carsView
}
override fun getItem(position: Int): Any {
return cars[position]
}
override fun getItemId(position: Int): Long {
return 0
}
override fun getCount(): Int {
return cars.count()
}
}
here is the list of cars data :
class Cars(val date: String, val id: Int, val title: String, val image: String, val category: String, val price: String,val distance: String,val gear: String,val oil: String,val year: String) {
override fun toString(): String {
return title
}
}
Try to use this code
try {
val list: List<CarsListData> = ArrayList()
val listCar = response.getJSONArray("listCar ")
for (i in 0 until listCar.length()) {
val carData=
listCar.getJSONObject(i)
CarsListData.id = response.getInt("id")
CarsListData.title = carData.getString("adTitle")
CarsListData.date = carData.getString("adDate")
CarsListData.price = carData.getDouble("adPrice")
CarsListData.category = carData.getString("category")
CarsListData.brand = carData.getString("brand")
CarsListData.model = carData.getString("brandModel")
CarsListData.distance = carData.getDouble("kilometer")
CarsListData.year = carData.getString("modelYear")
CarsListData.fuel = carData.getString("fuelType")
CarsListData.gear = carData.getString("gearType")
list.add(CarsListData)
}
val userDataChange = Intent(BROADCAST_USER_DATA_CHANGE)
LocalBroadcastManager.getInstance(context).sendBroadcast(userDataChange)
complete(true)
catch (e: JSONException) {
Log.d("JSON", "EXC" + e.localizedMessage)
}
Here is broadcasting the data in the listCarPage:
LocalBroadcastManager.getInstance(this).registerReceiver(userDataChangeReciever,
IntentFilter(BROADCAST_USER_DATA_CHANGE)
)
}
private val userDataChangeReciever = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// Here you can loop through the list
val data = list[0] // just example
carDetailsDate.text = data.date
carDetailsTitle.text = data.title
carDetailsCategory.text = data.category
carDetailsPrice.text = data.price.toString()
carDetailsDistance.text = data.distance.toString()
cardetailsGear.text = data.gear
carDetailsOil.text = data.fuel
carDetailsYear.text = data.year
}
}