Agregue datos a Recyclerview en Kotlin Android

Estoy usando Volley para leer una API JSON. Todo está funcionando en ese extremo. Cuando miro los times de llegada que obtengo de la API, son variados, que es lo que esperaría.

Salida JSON

10-24 08:34:17.831 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508849280 10-24 08:34:17.831 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508850180 10-24 08:34:17.831 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508850600 10-24 08:34:17.831 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508848920 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508851500 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508851980 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508849340 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508850000 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508849760 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508849340 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508848680 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508850000 10-24 08:34:17.832 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME = 1508851980 

Mi código agrega el número correcto de elementos a ArrayList, pero cuando miro los datos en el reciclador, aparecen múltiples ocurrencias del último elemento capturado:

 10-24 08:34:17.929 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.932 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.935 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.940 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.942 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.945 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.950 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.954 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 10-24 08:34:17.970 4671-4671/org.sherman.tony.nexttrain I/System.out: ARRIVAL TIME ===> 1508851980 

Este es el corazón de mi Código de actividad:

 // Get a list of train schedules // listOfTrains = ArrayList<TrainStatus>() volleyRequest = Volley.newRequestQueue(this) readTrains(url,station) } fun readTrains(url:String, station: String) { var listOfTrains = ArrayList<TrainStatus>() var trainStatus = TrainStatus() println("URL ===> $url") val jsonObjectRequest = JsonObjectRequest(Request.Method.GET,url, Response.Listener { response: JSONObject -> try { val responseMode = response.getJSONArray("mode") val responseModeRouteObj = responseMode.getJSONObject(0) val responseModeRouteObjRoute = responseModeRouteObj.getJSONArray("route") for (i in 0..responseModeRouteObjRoute.length() - 1){ val responseModeRouteObjRouteRouteObj = responseModeRouteObjRoute.getJSONObject(i) val responseModeRouteObjRouteRouteObjDirection = responseModeRouteObjRouteRouteObj.getJSONArray("direction") for (j in 0.. responseModeRouteObjRouteRouteObjDirection.length() - 1){ val responseModeRouteObjRouteRouteObjDirectionDirectionObj = responseModeRouteObjRouteRouteObjDirection.getJSONObject(j) val direction = responseModeRouteObjRouteRouteObjDirectionDirectionObj.getString("direction_id") trainStatus.direction_id = direction.toInt() val tripArray = responseModeRouteObjRouteRouteObjDirectionDirectionObj.getJSONArray("trip") for (k in 0..tripArray.length() - 1){ var tripArrayObj = tripArray.getJSONObject(k) var schArrival = tripArrayObj.getString("sch_arr_dt") trainStatus.sch_arr_time = schArrival.toLong() trainStatus.station = station println("ARRIVAL TIME = ${trainStatus.sch_arr_time}") // DEBUGGING print statement listOfTrains!!.add(trainStatus) } } } trainAdapter = TrainListAdapter(listOfTrains, this) layoutManager = LinearLayoutManager(this) // Set up recycler Adapter recyclerViewID.layoutManager = layoutManager recyclerViewID.adapter = trainAdapter trainAdapter!!.notifyDataSetChanged() } catch (e: JSONException){e.printStackTrace()} }, Response.ErrorListener { error: VolleyError? -> try{ error!!.printStackTrace() }catch(e:JSONException) { e.printStackTrace() } }) //val list:ArrayList<TrainList>? = null volleyRequest!!.add(jsonObjectRequest) println("SIZE OF ARRAY ===> ${listOfTrains.size}") return //return list } 

Y este es mi código de adaptador:

 package org.sherman.tony.nexttrain.adapters import android.content.Context import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import org.sherman.tony.nexttrain.models.TrainStatus import org.sherman.tony.nexttrain.R import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* class TrainListAdapter(var listOfTrains: ArrayList<TrainStatus>, val context: Context): RecyclerView.Adapter<TrainListAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup?, position: Int): ViewHolder { val view = LayoutInflater.from(context) .inflate(R.layout.station_lst_item, parent, false) return ViewHolder(view) } override fun getItemCount(): Int { return listOfTrains.size } override fun onBindViewHolder(holder: ViewHolder?, position: Int) { holder!!.bindView(listOfTrains[position]) } inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { var station = itemView.findViewById<TextView>(R.id.stationListTextViewID) var arrivalTime = itemView.findViewById<TextView>(R.id.timeScheduleID) fun bindView(train: TrainStatus){ var humanTime = readableTime(train.sch_arr_time!!) println("ARRIVAL TIME ===> ${train.sch_arr_time}") station.text = train.station.toString() //arrivalTime.text = humanTime arrivalTime.text = train.sch_arr_time.toString() } fun readableTime(milliSeconds: Long): String { var date = Date(milliSeconds) val dateFormat: DateFormat = SimpleDateFormat("H:mm") return dateFormat.format(date) } } } 

¿Cómo obtengo el adaptador para agregar los valores reales devueltos en lugar de múltiples copys del último elemento?

Gracias.

Creo que descubrí el problema. Estás creando una list de TrainStatus y obtienes esa list de una API remota. Para cada llamada itera y agrega el resultado dado. El problema radica en la statement de la variable trainStatus.

Hace un var trainStatus = TrainStatus () fuera de la function readTrains y luego, en cada iteración, cambia el valor de esa variable y la agrega a la list.

Lo hace pero no crea una nueva instancia para cada TrainStatus que desea agregar, por lo que agrega cada vez la misma instancia del mismo object a su list simplemente cambiando el valor en ella. De esta forma, cada elemento de la list apunta al mismo object TrainStatus, que contiene el valor del último elemento recibido de su request.

Para solucionar el problema, simplemente cree una nueva instancia cada vez que inicie una nueva iteración.

Así que cambie su código a:

 for (i in 0..responseModeRouteObjRoute.length() - 1){ val responseModeRouteObjRouteRouteObj = responseModeRouteObjRoute.getJSONObject(i) val responseModeRouteObjRouteRouteObjDirection = responseModeRouteObjRouteRouteObj.getJSONArray("direction") for (j in 0.. responseModeRouteObjRouteRouteObjDirection.length() - 1){ val responseModeRouteObjRouteRouteObjDirectionDirectionObj = responseModeRouteObjRouteRouteObjDirection.getJSONObject(j) val direction = responseModeRouteObjRouteRouteObjDirectionDirectionObj.getString("direction_id") val tripArray = responseModeRouteObjRouteRouteObjDirectionDirectionObj.getJSONArray("trip") for (k in 0..tripArray.length() - 1){ trainStatus.direction_id = TrainStatus() trainStatus.direction_id = direction.toInt() var tripArrayObj = tripArray.getJSONObject(k) var schArrival = tripArrayObj.getString("sch_arr_dt") trainStatus.sch_arr_time = schArrival.toLong() trainStatus.station = station println("ARRIVAL TIME = ${trainStatus.sch_arr_time}") // DEBUGGING print statement listOfTrains!!.add(trainStatus) } } } 

También te sugiero que no crees una nueva instancia del adaptador para cada llamada que hagas, sino que mantengas la list de trainstatus en el adaptador directamente.

  • ¿Cómo obtengo el resultado de una function de pepino?
  • java.lang.NoClassDefFoundError: kotlin / jvm / internal / Intrinsics en libgdx
  • UNRESOLVED_REFERENCE en widget (TextView) resuelto al elemento error en android-kotlin
  • Hello World en KotlinJS falla con Kotlin no está definido
  • Error: ejecución fallida para la tarea ': app: compileDebugKotlinAfterJava'
  • ¿Cómo almacenar variables temporales al inicializar un object Kotlin?
  • kotlin, ¿Cómo se puede cambiar el valor de la variable real en otra class a la que pasó mediante el parámetro?
  • Anotación de la invalidation de fuente Java generada (para Kotlin)
  • Kotlin - Cómo convertir String a ByteArray
  • ¿Qué corresponde exactamente a una Regex creada con Regex.fromLiteral ()?
  • Kotlin: Alcance interno: este