geloid
geloid

Reputation: 1

CoroutineScope is skipped

For some reasom my CoroutineScope just stopped working, though, nothing crucial has been changed and errors don't show up. The program skips it and my progress bar remains unchanged. Do you have any idea what could have possibly caused this issue?

class HomeFragment : BaseFragment(R.layout.fragment_home) {
    private var todayEventsCount: Int = 0
    private var todayCheckedEventsCount: Int = 0
    private val mHandler = Handler()
    private var mAdapter: FirebaseRecyclerAdapter<EventModel, EventsHolder>? = null
    private lateinit var mRunnable: Runnable
    private lateinit var barList: ArrayList<BarEntry>
    private lateinit var barDataSet: BarDataSet
    private lateinit var barData: BarData

    override fun onResume() {
        super.onResume()
        initFields()
    }

    override fun onPause() {
        super.onPause()
        home_events_list.removeAllViewsInLayout()
        todayCheckedEventsCount = 0
    }

    @SuppressLint("SetTextI18n")
    private fun initFields() {
        val progress: ProgressBar = ev_progress_bar
        val text: TextView = count
        getTodayEvents()

        CoroutineScope(Dispatchers.IO).launch {
            mRunnable = Runnable {
                if (mAdapter?.itemCount != 0) {
                    todayEventsCount = mAdapter?.itemCount!!

                    for (i in 0 until todayEventsCount) {
                        if (mAdapter?.getItem(i)!!.checked == "1") {
                            todayCheckedEventsCount++
                            progress.progress = todayCheckedEventsCount
                            text.text = progress.progress.toString() + "/" + progress.max.toString()
                        }
                    }
                    todayCheckedEventsCount = 0
                }
                mHandler.postDelayed(mRunnable, 30)
            }
            mHandler.post(mRunnable)
        }

        initChart()
    }

Upvotes: 0

Views: 206

Answers (1)

Tenfour04
Tenfour04

Reputation: 93882

There's no point in posting runnables if you're using a coroutine. Half the reason coroutines exist is to avoid this messy nested juggling of callbacks. There are also a few errors I see in your coroutine:

  • It runs on Dispatchers.IO, even though it never does anything blocking.
  • It runs on a throwaway CoroutineScope that is never cancelled. You should never use the CoroutineScope() constructor if you're not immediately assigning it to a variable or property through which you can cancel it at the appropriate time. You should be using viewLifeCycleOwner.lifecycleScope instead, since it's already set up to automatically cancel at the appropriate time to avoid crashes.
  • Your runnables you're posting are not canceled at the appropriate time, so even if you use the appropriate scope, they can still cause crashes. But as mentioned above, you don't need them in a coroutine.
  • (mAdapter?.itemCount != 0) will evaluate to true even if mAdapter is null, which will promptly cause a crash when you use mAdapter!!.

Fixed code looks like this. If this still doesn't do anything, you'll want to check to make sure your adapter is not null at the time this is called.

private fun initFields() {
    val progress: ProgressBar = ev_progress_bar
    val text: TextView = count
    getTodayEvents()

    viewLifeCycleOwner.lifecycleScope.launch {
        val adapter = mAdapter ?: return
        while (true) {
            if (adapter.itemCount != 0) {
                todayEventsCount = adapter.itemCount
                for (i in 0 until todayEventsCount) {
                    if (adapter.getItem(i).checked == "1") {
                        todayCheckedEventsCount++
                        progress.progress = todayCheckedEventsCount
                        text.text = progress.progress.toString() + "/" + progress.max.toString()
                    }
                }
                todayCheckedEventsCount = 0
            }
            delay(30)
        }
    }

    initChart()
}

I didn't try to follow your logic of what these todayEventsCount and todayCheckedEventsCount properties are. They probably should be locally defined variables in the coroutine.

You're also going to need some condition in the while loop that breaks you out of it. I didn't look closely enough to see what that condition should be. Your original code doesn't break the loop of reposting the runnable forever.

Upvotes: 1

Related Questions