当我在Arraylist中添加一个新元素时,它会替换所有当前元素吗



我有一个问题,当我向arraylist添加一个作为数据类的新元素时,它总是用新元素替换当前元素。你能告诉我问题出在哪里,解决办法是什么吗。提前感谢

型号

import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Parcelize
data class ScheduleModel(
@field:SerializedName("user_available_id")
var userAvailableId: String? = null,
@field:SerializedName("teacher_id")
var teacherId: String? = null,
@field:SerializedName("schedule")
var schedule: ArrayList<schedule?>? = null

) : Parcelable
@Parcelize
data class schedule(
@field:SerializedName("event_id")
var eventId: String? = null,
@field:SerializedName("schedule_time")
var scheduleTime: String? = null,
@field:SerializedName("status")
var status: String? = null
) : Parcelable

我正在使用recyclerview向arraylist添加元素。元素是数据类模型。下面是流程,我首先从API获取数据,然后用recyclerview显示数据。然后在显示之后,我想获取显示数据并将其保存到数组列表中。在将数据保存到arraylist后,arraylist会将数据发送到api,如下所示:

{
"user_available_id": 702,
"teacher_id" : 3207,
"schedule" : [{
"event_id" : 47533,
"schedule_time" : "2020-11-30 07:00:00",
"status" :1
},
{
"event_id" : 47532,
"schedule_time" : "2020-11-30 06:30:00",
"status" :1
}]
}

当我向arraylist添加新数据时,保存到arraylist的数据总是用新数据覆盖当前数据。

功能

private suspend fun getMultiSlotJadwal(id: String, date: String) {
jamList.clear()
val networkConfig =
NetworkConfig().getTeacher().getTeacherScheduleAvailability(token, id, date)
if (networkConfig.isSuccessful) {
if (networkConfig.body()!!.availability!!.isEmpty()) {
binding.rvSlot.visibility = View.GONE
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Jam tidak tersedia",
Toast.LENGTH_SHORT
).show()
}
} else {
for (slot in networkConfig.body()!!.availability!!) {
//convert tanggal start ke millis
val tanggalSlot = slot!!.start!!.toDate().formatTo("yyyy-MM-dd HH:mm")
val tanggalInMillis = convertToMillis(tanggalSlot)
//ambil tanggal sekarang
val myFormat = "yyyy-MM-dd HH:mm" // format tanggal
val calendar = Calendar.getInstance()
val time = calendar.time
val sdf = SimpleDateFormat(myFormat, Locale.getDefault())
val curdate = sdf.format(time) //diconvert ke tanggal local
val curDateinMillis = convertToMillis(curdate) // convert ke millis
val hasilDate = tanggalInMillis - curDateinMillis
val tanggalJam = hasilDate / 3600000 //diubah dari millis ke jam
if (tanggalJam >= 6) {
jamList.add(slot)
val sortJamList = jamList.sortedBy { jamList -> jamList.start }

binding.rvSlot.visibility = View.VISIBLE
val adapter = SlotJamMultiAdapter(sortJamList) {
teacher_id = it.teacherId.toString()
scheduleModel.userAvailableId = user_avalaible_id //model
scheduleModel.teacherId = teacher_id
scheduleItem.scheduleTime = it.start.toString()
scheduleItem.status = "1"
scheduleItem.eventId = it.id.toString()
scheduleList.add(scheduleItem) // array list
scheduleModel.schedule = scheduleList
Log.d(TAG, "getMultiSlotJadwal: $scheduleList")
itemClicked = true
changeBackgroundButtonSesi2()
}
adapter.submitList(sortJamList)
binding.rvSlot.adapter = adapter

}
}
}
} else {
Handler(Looper.getMainLooper()).post {
Toast.makeText(
this,
"Jam tidak tersedia",
Toast.LENGTH_SHORT
).show()
}
}
}

编辑这是我使用diffutils后的适配器适配器


class SlotJamMultiAdapter(
private var data: List<AvailabilitySlotItem>,
private val listener: (AvailabilitySlotItem) -> Unit
) : RecyclerView.Adapter<SlotJamMultiAdapter.LeagueViewHolder>() {
private lateinit var ContextAdapter: Context
class LeagueViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvJam = view.findViewById<TextView>(R.id.tv_slot_jam_list)
val cvSlot = view.findViewById<CardView>(R.id.cv_slot_list)
val llSlot = view.findViewById<LinearLayout>(R.id.ll_cv_slot)
fun bidnItem(
data: AvailabilitySlotItem,
listener: (AvailabilitySlotItem) -> Unit,
context: Context,
position: Int
) {
val jam = data.start!!.toDate().formatTo("HH:mm")
tvJam.text = jam
itemView.setOnClickListener {
listener(data)
}
}
private fun String.toDate(
dateFormat: String = "yyyy-MM-dd HH:mm:ss",
timeZone: TimeZone = TimeZone.getTimeZone("UTC")
): Date {
val parser = SimpleDateFormat(dateFormat, Locale.getDefault())
parser.timeZone = timeZone
return parser.parse(this)
}
private fun Date.formatTo(
dateFormat: String,
timeZone: TimeZone = TimeZone.getDefault()
): String {
val formatter = SimpleDateFormat(dateFormat, Locale.getDefault())
formatter.timeZone = timeZone
return formatter.format(this)
}
}
class slotItemDiffCallback(
var oldSlotList: List<AvailabilitySlotItem>,
var newSlotList: List<AvailabilitySlotItem>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldSlotList.size
}
override fun getNewListSize(): Int {
return newSlotList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return (oldSlotList.get(oldItemPosition).id == newSlotList.get(newItemPosition).id)
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldSlotList.get(oldItemPosition).equals(newSlotList.get(newItemPosition))
}
}

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): SlotJamMultiAdapter.LeagueViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
ContextAdapter = parent.context
val inflatedView: View = layoutInflater.inflate(R.layout.slot_list, parent, false)
return SlotJamMultiAdapter.LeagueViewHolder(inflatedView)
}
override fun onBindViewHolder(holder: SlotJamMultiAdapter.LeagueViewHolder, position: Int) {
holder.bidnItem(data[position], listener, ContextAdapter, position)
}
override fun getItemCount(): Int = data.size
fun submitList(availabilitySlotItemList: List<AvailabilitySlotItem>) {
val oldList = data
val diffResult:DiffUtil.DiffResult=DiffUtil.calculateDiff(
slotItemDiffCallback(
oldList,availabilitySlotItemList
)
)
data = availabilitySlotItemList
diffResult.dispatchUpdatesTo(this)
}
}

因为每次使用getMultiSlotJadwal((获取列表时,都会创建一个新的适配器实例并将其分配给recyclerview。

binding.rvSlot.adapter = SlotJamMultiAdapter(sortJamList) { }

继续引用指定的适配器,然后当您从服务器获得新列表时,将该列表提供给您以前引用的适配器。

您可以搜索ListAdatper/DiffUtil.Callback,他们会代表您检查新列表中的项目是否与旧列表中的相同。你所要做的就是像下面的一样将新列表提交给ListAdapter

val newList = getNewListFromServer()
myAdapter.submitList(list)

更新

好的,对于调度模型

class ScheduleModel(
val userAvailableId : String?,
val teacherId : String?,
val schedule : List<String>?
) {
class ScheduleDiffUtilCallback : DiffUtil.ItemCallback<ScheduleModel>(){
override fun areItemsTheSame(oldItem: ScheduleModel, newItem: ScheduleModel): Boolean {
return true
// set the way how to identify if the newItem is the same as the oldItem
}
override fun areContentsTheSame(oldItem: ScheduleModel, newItem: ScheduleModel): Boolean {
return true
// set the way how to identify if the newItem's contents is the same as the oldItem's contents
}
}
}

对于适配器

class SlotJamMultiAdapter : ListAdapter<ScheduleModel, SlotJamMultiAdapter.ViewHolder>(
ScheduleModel.ScheduleDiffUtilCallback()
){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.item_schedule, parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)
holder.bind(item)
}
class ViewHolder(root : View) : RecyclerView.ViewHolder(root) {
fun bind(item : ScheduleModel) {
//bind data to view here
}
}
}

您实际上没有引用数据的节点在适配器类中列出自己。ListAdapter将引用它,并执行更新数据所需的所有操作。

你所要做的就是,在片段或活动中

val adapter = SlotJamMultiAdapter()
rc.adapter = adapter

当你的数据发生变化时(如果你得到了新的列表(

adapter.submitList(newList)

注意,我没有创建一个新的适配器实例,我引用的是连接到recyclerview的旧适配器,我正在重用它

最新更新