Recyclerview 不断被重置

Recyclerview keep being reset

我的回收站视图有问题,我想每秒刷新一次,为此我使用了一个创建新请求的计时器,但我认为我的回收站视图已被销毁并直接重新创建,当我正在滚动它,它总是每秒都回到顶部。这是我的片段,我听说过 layoutmanager 但不知道如何使用它,它有链接吗?

class DlFragment (private val context: MainActivity): Fragment(){

private var myTimer: Timer? = null

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {

    val view = inflater.inflate(R.layout.fragment_dl,container, false)

    val dlRecyclerView = view?.findViewById<RecyclerView>(R.id.dl_list_recycle_view)

    myTimer = Timer()

    myTimer!!.schedule(object : TimerTask() {
        override fun run() {
            getDlList(dlRecyclerView)
        }
    }, 0, 1000)
    
    val comfirmButton= view.findViewById<Button>(R.id.input_post_dl_button)
    comfirmButton.setOnClickListener { postDl(view) }                          

    return view
}

private fun getDlList(dlRecyclerView: RecyclerView?) {
    GlobalScope.launch(Dispatchers.Main) {
        try {
            val response = ApiClientQnap.apiServiceQnap.getQuery(0,20,"all","all",ApiClientQnap.sid)

            if (response.isSuccessful && response.body() != null) {
                val content = response.body()
                if (content != null) {
                    //println(content)
                    //val dlRecyclerView = view?.findViewById<RecyclerView>(R.id.dl_list_recycle_view)
                    dlRecyclerView?.adapter = DlAdapter(context,content.data)

                }
            } else { println("Error Occurred: ${response.message()}") }
        } catch (e: Exception) {println("Error Occurred: ${e.message}") }
    }
}

private fun postDl(view: View){

    val url_Dl = view.findViewById<EditText>(R.id.input_post_dl_text)

    GlobalScope.launch(Dispatchers.Main) {
        try {
            val response = ApiClientQnap.apiServiceQnap.postDL("Films","Films",
                url_Dl.text.toString(),ApiClientQnap.sid)

            if (response.isSuccessful && response.body() != null) {
                val content = response.body()
                println(response.body())
                if (content != null) {
                    if(content.error == 0) {
                        Toast.makeText(context, "yeee", Toast.LENGTH_LONG).show()
                        url_Dl.text.clear()
                    }
                    else
                        Toast.makeText(context, "no", Toast.LENGTH_LONG).show()
                }
            } else { println("Error Occurred: ${response.message()}") }
        } catch (e: Exception) {println("Error Occurred: ${e.message}") }
    }
}

编辑:这是我的 DlAdapter

class DlAdapter(
    val context: MainActivity,
    private var dlList: ArrayList<Data>
    ) : RecyclerView.Adapter<DlAdapter.ViewHolder>() {


    class ViewHolder(view : View): RecyclerView.ViewHolder(view){
        val dl_title = view.findViewById<TextView>(R.id.dl_title)
        val dl_progress = view.findViewById<TextView>(R.id.dl_progress)
        val dl_speed = view.findViewById<TextView>(R.id.dl_speed)
        val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)

    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {


        val view = LayoutInflater
            .from(parent.context)
            .inflate(R.layout.fragment_dl_list,parent,false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        val currentDl = dlList[position]

        holder.dl_title.text = currentDl.source_name

        holder.progressBar.progress = (currentDl.progress!!)

        when (currentDl.state) {
            5 -> holder.dl_progress.text = ("Terminé")
            2 -> holder.dl_progress.text = ("Arrété")
            4 -> holder.dl_progress.text = ("Echec")
            1 -> holder.dl_progress.text = (currentDl.progress.toString() + " % En pause")
            104 -> {
                holder.dl_progress.text = (currentDl.progress.toString() + " %")
                var toFloat = currentDl.down_rate?.toFloat()
                toFloat = toFloat?.div(1000000)   
                holder.dl_speed.text = (toFloat.toString()+" Mo")

            }
        }
    }

    override fun getItemCount(): Int = dlList.size

    fun updateData(newData: ArrayList<Data>) {
        dlList.clear()
        dlList.addAll(newData)
        notifyDataSetChanged()
    }
}

正如@hardartcore 所建议的,您可以尝试将 RecyclerView.Adapter 转换为 ListAdapter 并使用 DiffUtil.ItemCallback class.

尝试像这样转换您的适配器:

class DlAdapter : ListAdapter<Data, DlAdapter.ViewHolder>(DlDiffCallback()) {

    class ViewHolder(view : View): RecyclerView.ViewHolder(view){
        val dl_title = view.findViewById<TextView>(R.id.dl_title)
        val dl_progress = view.findViewById<TextView>(R.id.dl_progress)
        val dl_speed = view.findViewById<TextView>(R.id.dl_speed)
        val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater
            .from(parent.context)
            .inflate(R.layout.fragment_dl_list,parent,false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // Use the getItem method to retrieve a specific item
        val currentDl = getItem(position)

        holder.dl_title.text = currentDl.source_name

        holder.progressBar.progress = (currentDl.progress!!)

        when (currentDl.state) {
            5 -> holder.dl_progress.text = ("Terminé")
            2 -> holder.dl_progress.text = ("Arrété")
            4 -> holder.dl_progress.text = ("Echec")
            1 -> holder.dl_progress.text = (currentDl.progress.toString() + " % En pause")
            104 -> {
                holder.dl_progress.text = (currentDl.progress.toString() + " %")
                var toFloat = currentDl.down_rate?.toFloat()
                toFloat = toFloat?.div(1000000)   
                holder.dl_speed.text = (toFloat.toString()+" Mo")
            }
        }
    }
}

class DlDiffCallback : DiffUtil.ItemCallback<Data>() {
    // Change this method comparisons based on your equality conditions
    override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean = oldItem.id == newItem.id
    override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean = oldItem == newItem
}

然后您可以使用 submitList 方法更新您的 RecyclerView 适配器:

val adapter = DlAdapter()
adapter.submitList(content.data)