How to properly wait for HandlerThread to start before doing something?

709 Views Asked by At

In My project sometimes the created thread does not start as fast as it should be, This happens on a minimal occasions but mostly will happen on slow/older phones.

I my Thread like..

class DBThread(threadName: String) : HandlerThread(threadName) {

private var mWorkerHandler: Handler? = null

    override fun onLooperPrepared() {
        super.onLooperPrepared()
        mWorkerHandler = Handler(looper)
    }

    fun createTask(task: Runnable) {
        mWorkerHandler?.post(task)
    }
}

and when i use it and call on activity..

//this will handle db queries on background and not on main ui thread
var mDbThread: DBThread = DBThread("dbThread")

//use this to interact to main ui thread from different thread
val mUiHandler = Handler()
var mDb: LocalDatabase? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    mDbThread.start()
    mDb = LocalDatabase.getInstance(this)

    fetchAndSetList()

}

override fun onDestroy() {
    super.onDestroy()

    LocalDatabase.destroyInstance()
    mDbThread.quitSafely()
}


private fun fetchAndSetList(){

    mDbThread.createTask(Runnable {
        val list = getList()
        mUiHandler.post {
            // this sometimes does not trigger
            setList(list)
        }
    })
}

the function setList does not trigger on sometimes. And so i did something like this.

fun createTask(task: Runnable) {
    if(mWorkerHandler == null ){
        createTask(task)
        return
    }
    mWorkerHandler?.post(task)
}

the modified action seems to work however I'm not quite sure if this is a SAFE way to do this. Thank you in advance.

1

There are 1 best solutions below

0
On BEST ANSWER

I think the reason why mWorkerhandler is null is because Thread.start will create the new VMThread and start the looper in the VMThread. The whole flow is asynchronous so when onLooperPrepared actually is called, it's too late because "fetchAndSetList" is already trying to use mWorkerHandler

The solution is create the handler outside of the HandlerThread:

Handler workerHandler;
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    mDbThread.start()
    workerHandler = new Handler(mDbThread.getLooper());
    mDb = LocalDatabase.getInstance(this)

    fetchAndSetList()
}

private fun fetchAndSetList(){
    workerHandler.post(Runnable {
        val list = getList()
        mUiHandler.post {
            // this sometimes does not trigger
            setList(list)
        }
   })
}