简体   繁体   English

如何在Android上使用多个计时器进入recyclerView

[英]How to use multiple timer into recyclerView on Android

In my application i want use multiple CountDownerTimer for show offer times into RecyclerView .在我的应用程序中,我想使用多个CountDownerTimer来显示RecyclerView报价时间。
For write this application i used Kotlin language.为了编写这个应用程序,我使用了Kotlin语言。
I write below codes, but when scrolling on recyclerView 's items start again this timer !我写了下面的代码,但是当滚动recyclerView的项目时,这个计时器又开始了!

My mean is, timer started from 4:19 sec, when scrolling on items and after 10sec show me 4:19 again instead of 4:09 !我的意思是,计时器从4:19秒开始,当滚动项目时, 10 秒后再次显示4:19而不是4:09

Activity codes:活动代码:

class MainActivity : AppCompatActivity() {

    private lateinit var apisList: ApisList
    private lateinit var retrofit: Retrofit
    private lateinit var todayAdapter: AuctionsTodayAdapter
    private val todayModel: MutableList<Today> = mutableListOf()
    private lateinit var layoutManager: RecyclerView.LayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //Initialize
        retrofit = ApiClient.instance
        apisList = retrofit.create(ApisList::class.java)
        todayAdapter = AuctionsTodayAdapter(themedContext, todayModel)
        layoutManager = LinearLayoutManager(themedContext)
        //RecyclerView
        main_list.setHasFixedSize(true)
        main_list.layoutManager = layoutManager
        main_list.adapter = todayAdapter

        if (isNetworkAvailable()) getData(1, 10)
    }

    private fun getData(page: Int, limit: Int) {
        main_loader.visibility = View.VISIBLE
        val call = apisList.getAuctionsToday(page, limit)
        call.let {
            it.enqueue(object : Callback<AuctionsTodayResponse> {
                override fun onFailure(call: Call<AuctionsTodayResponse>, t: Throwable) {
                    main_loader.visibility = View.GONE
                    Log.e("auctionsTodayList", t.message)
                }

                override fun onResponse(call: Call<AuctionsTodayResponse>, response: Response<AuctionsTodayResponse>) {
                    if (response.isSuccessful) {
                        response.body()?.let { itBody ->
                            main_loader.visibility = View.GONE
                            if (itBody.toString().isNotEmpty()) {
                                todayModel.clear()
                                todayModel.addAll(itBody.res.today)
                                todayAdapter.notifyDataSetChanged()
                            }
                        }
                    }
                }
            })
        }
    }
}

Adapter codes:适配器代码:

class AuctionsTodayAdapter(val context: Context, val model: MutableList<Today>) :
    RecyclerView.Adapter<AuctionsTodayAdapter.MyHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.row_main_list, parent, false)
        val holder = MyHolder(view)

        //holder.setIsRecyclable(false)

        return holder
    }

    override fun getItemCount(): Int {
        return model.size
    }

    override fun onBindViewHolder(holder: MyHolder, position: Int) {
        val modelUse = model[position]
        holder.setData(modelUse)



        if (holder.newCountDownTimer != null) {
            holder.newCountDownTimer!!.cancel()
        }
        var timer = modelUse.calculateEnd

        timer = timer * 1000

        holder.newCountDownTimer = object : CountDownTimer(timer, 1000) {
            override fun onTick(millisUntilFinished: Long) {
                var seconds = (millisUntilFinished / 1000).toInt()
                val hours = seconds / (60 * 60)
                val tempMint = seconds - hours * 60 * 60
                val minutes = tempMint / 60
                seconds = tempMint - minutes * 60
                holder.rowMain_timer.rowMain_timer.text =
                    String.format("%02d", hours) + ":" + String.format(
                        "%02d",
                        minutes
                    ) + ":" + String.format("%02d", seconds)
            }

            override fun onFinish() {
                holder.rowMain_timer.text = "00:00:00"
            }
        }.start()

    }

    inner class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        var newCountDownTimer: CountDownTimer? = null

        lateinit var rowMain_timer: TextView

        init {
            rowMain_timer = itemView.findViewById(R.id.rowMain_timer)
        }

        fun setData(model: Today) {
            model.image.let {
                Glide.with(context)
                    .load(Constants.MAIN_BASE_URL + it)
                    .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.RESOURCE))
                    .into(itemView.rowMain_img)
            }
            model.title.let { itemView.rowMain_title.text = it }
        }
}

How can I fix it?我该如何解决?

Because your code is written that way.因为你的代码是这样写的。

onBindViewHolder(..) is called whenever you scroll up/down and the view goes outside of visible area.每当您向上/向下滚动并且视图超出可见区域时,就会调用onBindViewHolder(..) Then that view is recycled and bound again to new list item (from model list).然后该视图被回收并再次绑定到新列表项(来自模型列表)。 That's how it got the name RecyclerView .这就是它获得名称RecyclerView

To solve your problem, you need to put your countdown timer initialization codes inside model list item initialization (eg Today constructor).要解决您的问题,您需要将倒数计时器初始化代码放在模型列表项初始化(例如Today构造函数)中。

Then the countdown timer will start and remain running within the Today object and inside onBindViewHolder(..) just grab the remaining time value from that Today object.然后倒数计时器将启动并在 Today 对象内保持运行,而在onBindViewHolder(..)只需从该Today对象中获取剩余时间值。

Hope this helps!!希望这可以帮助!!

Update I am not experienced in kotlin.更新我对 kotlin 没有经验。 So you may need to modify it according to kotlin.所以你可能需要根据 kotlin 修改它。 At some point you have MutableList<Today> preparation code right?在某些时候你有MutableList<Today>准备代码对吗?

while creating a Today object, pass the adapter object as a constructor parameter.在创建 Today 对象时,将适配器对象作为构造函数参数传递。

The following block should be inside your Today class.下面的块应该在你的Today类中。

 var newCountDownTimer : CountDownTimer var currentVal : String init { newCountDownTimer = object : CountDownTimer(timer, 1000) { override fun onTick(millisUntilFinished: Long) { var seconds = (millisUntilFinished / 1000).toInt() val hours = seconds / (60 * 60) val tempMint = seconds - hours * 60 * 60 val minutes = tempMint / 60 seconds = tempMint - minutes * 60 currentVal = String.format("%02d", hours) + ":" + String.format( "%02d", minutes ) + ":" + String.format("%02d", seconds) // call adapter.notifyItemChanged(..) here } override fun onFinish() { //here you should call the adapter.notifyItemChanged(..) function with the position of this model in the model list } }.start() }

your onBindViewHolder should look like this:您的onBindViewHolder应如下所示:

 override fun onBindViewHolder(holder: MyHolder, position: Int) { val modelUse = model[position] holder.setData(modelUse) }

inside Holder.setData(..) function add this codeHolder.setData(..)函数中添加此代码

rowMain_timer.text = model.currentVal

Let me know if it helps.如果有帮助,请告诉我。

have you tried making use of 1. onSaveInstanceState(Bundle state) 2.Restore state in the onRestoreInstanceState() 3. and onResume() .您是否尝试过在onRestoreInstanceState() 3. 和onResume()使用 1. onSaveInstanceState(Bundle state) 2.Restore 状态。

this way you can keep track on your RecyclerList data.这样您就可以跟踪您的 RecyclerList 数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM