2
\$\begingroup\$

I often come around a requirement where we have to perform a repetitive task on the user's screen (for eg, updating a counter like flash sale/ live class timer, autoscrolling the banner, etc) . I have written this small file which performs a basic task of pressing a button every 2 seconds for a total of 4 times as a general example and my approach to this problem Please review and provide your inputs about weather this would be a correct approach or not.

class AVCActivity : AppCompatActivity() {
    private var scrollInterval = 0
    private var run4Times = false
    private val handler = Handler()
    private var count = 0
   

    override fun onCreate(b:Bundle) {
        scrollInterval = 2000
        run4Times = api.runRepetitiveTask() 
        // task will start in onResume
    }

    override fun onPause() {
        super.onPause()
        handler.clearStack()
    }

    override fun onResume() {
        super.onResume()
        if(run4Times){
            handler.clearStack().postDelayed(scrollTask,scrollInterval.toLong())
        }
    }

    private fun Handler.clearStack():Handler{
        this.removeCallbacksAndMessages(null)
        return this
    }

    private val scrollTask = object : Runnable{
        override fun run() {
            if(count < 4){
                count + =1
                btHello?.performOnClick()
                handler.clearStack().postDelayed(this,scrollInterval.toLong())
            }
            else{
                run4Times = false
                handler.clearStack()
            }
        }
    }
}

Some details:

  1. handler fires the runnable every 2 seconds via recursion for 3 times . on the 4th time, the runnable clears the handler and closes handler recursion
  2. handler gets started in onResume and stopped in onPause to handle case where user has closed the screen before completion of the original task. The condition to weather make the handler fire the runnable is handled via a global variable, initialised in onCreate() .i,e only once .
  3. handler is NOT started in onCreate because this will cause the handler to run same runnable twice(since onCreate->onResume) . this usually causes a bug where we assume the runnable to run once every 2 seconds, but ends up with 2 runnables running every 2 seconds
  4. every postCall is made after handler.removeCallbacksAndMessages(null) (via extension function clearStack() ) , thereby removing any unprocessed runnables. this is especially required in a case of onResume() , since onResume can be called multiple times and this could lead to same problem as point 3. using this function prevents this case from occurring.
  5. variables like handler and runnable are global to prevent duplication/re assigning.
  6. it is safe to access ui views in runnable because the handler is going to run the runnable in main thread (my assumption)

Anything else should i be considering? Is it a good general approach? any memory leaks in this approach?

PS : I think this question might have been asked before, but i am not sure if this has been asked in context to Android/kotlin. Kindly point me to an already asked question with better approach if this is repetitive

\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.