I'm facing a problem with my recycler view, I'd wanted to refresh it every second, for that I use a timer which creates new request, but I think that my recyclerview is destroyed and directly recreated, when I'm scrolling it keep always returning to the top every second. Here is my fragment, I heard about layoutmanager but don't really know how to use it, is it linked?
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}") }
}
}
Edit: Here's my 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()
}
}
CodePudding user response:
As @hardartcore suggested, you can try to convert the RecyclerView.Adapter
to a ListAdapter
and use a DiffUtil.ItemCallback
class.
Try to convert your adapter like this:
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
}
You can then update your RecyclerView
adapter by using the submitList
method:
val adapter = DlAdapter()
adapter.submitList(content.data)