androidengineers.Book a session
โ† All interview questions
ThreadIntermediate5 min

How to communicate between Threads in Android?

Answer

Ways to Communicate Between Threads

1. Handler and Looper (Traditional Android Way)

// Create Handler on main thread
val mainHandler = Handler(Looper.getMainLooper())

// Background thread sends message to main thread
Thread {
    val result = fetchData()
    mainHandler.post {
        textView.text = result  // Runs on main thread
    }
}.start()

2. Handler with Messages

val handler = object : Handler(Looper.getMainLooper()) {
    override fun handleMessage(msg: Message) {
        when (msg.what) {
            MSG_UPDATE_PROGRESS -> {
                progressBar.progress = msg.arg1
            }
            MSG_COMPLETE -> {
                val result = msg.obj as String
                textView.text = result
            }
        }
    }
}

// From background thread
Thread {
    for (i in 0..100) {
        handler.sendMessage(Message.obtain().apply {
            what = MSG_UPDATE_PROGRESS
            arg1 = i
        })
    }
    handler.sendMessage(Message.obtain().apply {
        what = MSG_COMPLETE
        obj = "Done!"
    })
}.start()

3. runOnUiThread() (Activity only)

Thread {
    val data = fetchData()
    runOnUiThread {
        textView.text = data
    }
}.start()

4. View.post()

Thread {
    val data = fetchData()
    textView.post {
        textView.text = data
    }
}.start()

5. LiveData (Lifecycle-aware)

class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<String>()
    val data: LiveData<String> = _data
    
    fun fetchData() {
        viewModelScope.launch(Dispatchers.IO) {
            val result = repository.getData()
            _data.postValue(result)  // Thread-safe!
        }
    }
}

// In Activity/Fragment
viewModel.data.observe(this) { result ->
    textView.text = result  // Automatically on main thread
}

6. Kotlin Coroutines (Recommended)

lifecycleScope.launch {
    val data = withContext(Dispatchers.IO) {
        fetchData()  // Background thread
    }
    // Automatically back on main thread
    textView.text = data
}

7. Flow (Reactive Streams)

fun dataFlow(): Flow<String> = flow {
    emit(fetchData())
}.flowOn(Dispatchers.IO)

// Collect on main thread
lifecycleScope.launch {
    dataFlow().collect { data ->
        textView.text = data
    }
}

Comparison

MethodLifecycle-awareModernRecommended
HandlerNoNoLegacy code
runOnUiThreadNoNoQuick fixes
LiveDataYesYesMVVM
CoroutinesYes*Yesโœ… Best
FlowYes*Yesโœ… Reactive

*With lifecycleScope/viewModelScope

Best Practice

Use Coroutines with lifecycleScope or viewModelScope for automatic lifecycle management and clean, readable code.

Mark this when you can explain the answer in your own words.

Share & Help Others

Help fellow developers prepare for interviews

Sharing helps the Android community grow ๐Ÿ’š

Keep practising