当前位置: 首页 > 知识库问答 >
问题:

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

那宏大
2023-03-14

我有一个问题,当我向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)
    }

}

共有1个答案

岳彬炳
2023-03-14

因为每次使用getMultiSlotJadwal()获取列表时,您都会创建一个新的适配器实例并将其分配给回收人员视图。

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

继续引用分配的适配器,然后当从服务器获取新列表时,将该列表提供给先前引用的适配器。

您可以搜索ListAdatper/DiffUtil。回调时,它们会代表您检查新列表中的项目是否与旧列表中的项目相同。您所要做的就是将新列表提交到下面的ListAdapter

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

更新了

好的,对于ScheduleModel

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的旧适配器,并且正在重用它

 类似资料:
  • 问题内容: 首先,对无法提供任何源代码表示歉意。我的项目很大,将所有内容链接起来都是不切实际的,而且我还无法缩小非常烦人的问题。我将尽力在这里进行解释。 我在代码的每个循环中动态创建类的新实例。在循环中会为该实例动态地提供几个属性,例如’name’。在每个循环的最后,新生成的实例将添加到另一个第3类中保存的ArrayList中。 但是,问题在于,无论出于何种原因添加新元素时,所有先前的元素都会更改

  • 我是Java新手,使用对象的编写Java小应用程序。 我以为ArrayList对象会为将要添加到列表中的每个新元素添加新索引,而从不修改以前的元素。我的代码怎么了?

  • 问题内容: 下面有一个for循环代码。我通过调用一个自定义显示函数发现aBook arrayList对象仅添加了最后一个类对象三次。为什么会这样呢? 这是我的LiFiAddressBook类 } 问题答案: 由于使用static关键字,每次 调用构造函数时,旧值都会被新值覆盖,并且在打印列表中的元素时,LiFiAddressBook类的对象变量将指向相同的对象。因此打印相似的对象。 需要明确的是,

  • 给定两个排序整数数组A和B,将B合并为A作为一个排序数组。 注意:您必须修改数组A,以包含A和B的合并。不要在代码中输出任何内容。提示:C用户,请将结果malloc到一个新的数组中并返回结果。 如果A和B中初始化的元素数分别为m和n,则代码执行后数组A的结果大小应为m+n

  • 在本例中,我的代码是: CSS: } 我有一些代码用于我希望使用的指示器,它是发光效果:

  • 问题内容: 我对Java编程还是很陌生,我正在尝试使用以下代码来更新an的现有值: 我想打印而不是打印,但得到的结果仍然是。我要打印。我怎样才能做到这一点?谢谢。 问题答案: 使用该方法将旧值替换为新值。

  • 当我使用System.out.println静态方法时,下面的Java程序显示ArrayList中的所有元素。但是,当我在方法中返回列表时,它只显示ArrayList中的一个元素。我希望你能给我一些指点,让我知道你做错了什么:

  • 问题内容: 我以为链表在添加元素时应该比数组表快?我只是测试了添加,排序和搜索元素(数组列表,链表,哈希集)需要多长时间。我只是对数组列表和链接列表使用java.util类…使用每个类都可以使用的两个add(object)方法。 arraylist在填充列表中执行链表…并在列表中进行线性搜索。 这是正确的吗?我在执行中做错了吗? *_ __ _ _ __ _编辑 __ * __ __ * * 我只