Fix Android CalledFromWrongThreadException

In this tutorial, we shall learn to fix Android Exception CalledFromWrongThreadException : Only the original thread that created a view hierarchy can touch its views.

This error usually appears when a background thread tries to read from or update a view such as TextView, Button, RecyclerView, ProgressBar, or any other UI element that belongs to the Android main thread.

The fix is simple: keep the long-running work in the background thread, but move the UI update back to the main thread by using runOnUiThread(), View.post(), a Handler attached to the main Looper, or Kotlin coroutines with Dispatchers.Main.

Why Android says only the original thread can touch its views

Android views are not designed to be updated safely from multiple threads at the same time. The main thread, also called the UI thread, creates the activity layout and handles drawing, input events, layout passes, and view updates. When another thread tries to change the same view hierarchy directly, Android throws CalledFromWrongThreadException to prevent unsafe UI access.

You might have come across this error while from a thread you are trying to set some property of a View or extract some property of a View, that belong to UI thread.

An important point to be remembered while trying to do any operations with UI views is that, only UI thread that created a view hierarchy can touch its views.

Example that causes CalledFromWrongThreadException in Kotlin Android

Following is simple example, where we try to access a TextView (that belong to UI thread) in another thread.

MainActivity.kt

package com.tutorialkart.runonuithreadexample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start some dummy thread that is different from UI thread
        Thread(Runnable {
            // performing some dummy time taking operation
            var i=0;
            while(i<Int.MAX_VALUE){
                i++
            }

            // try to touch View of UI thread
            this.textview_msg.text = "Updated from other Thread"
        }).start()
    }
}

You might see below exception in Logcat

android.view.ViewRootImpl$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views.
     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7534)
     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1200)
     at android.view.View.requestLayout(View.java:20044)

Following is the line of code that caused this exception

</>
Copy
this.textview_msg.text = "Updated from other Thread"

In general, you touched an UI View from another thread, which you should not do without any help.

Fix CalledFromWrongThreadException with runOnUiThread()

To fix this error, wrap the code that has to be executed on UI thread in a Runnable instance passed to runOnUiThread() method.

</>
Copy
this@MainActivity.runOnUiThread(java.lang.Runnable {
    this.textview_msg.text = "Updated from other Thread"
})

Following is the corrected MainActivity.kt

MainActivity.kt

</>
Copy
package com.tutorialkart.runonuithreadexample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // start some dummy thread that is different from UI thread
        Thread(Runnable {
            // performing some dummy time taking operation
            var i=0;
            while(i<Int.MAX_VALUE){
                i++
            }

            // try to touch View of UI thread
            this@MainActivity.runOnUiThread(java.lang.Runnable {
                this.textview_msg.text = "Updated from other Thread"
            })
        }).start()
    }
}

Modern Kotlin Android example using View Binding and runOnUiThread()

The earlier example uses Kotlin Android synthetic view access, which was common in older Android projects. In current Kotlin Android projects, View Binding is a safer and more common option. The threading rule is still the same: do the heavy work away from the main thread, then update the UI on the main thread.

</>
Copy
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

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

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        Thread {
            // Background work
            val message = "Updated from background work"

            // UI update must run on the main thread
            runOnUiThread {
                binding.textviewMsg.text = message
            }
        }.start()
    }
}

In this version, the background thread prepares the value, and only the final TextView assignment is posted to the UI thread.

Fix the original thread view hierarchy error with View.post()

If you already have access to the view that has to be updated, you can also call post() on that view. The Runnable is added to the view’s message queue and runs on the thread that owns the view.

</>
Copy
Thread {
    val message = "Updated using View.post()"

    binding.textviewMsg.post {
        binding.textviewMsg.text = message
    }
}.start()

This is useful when the update is closely related to a particular view. For activity-level UI updates, runOnUiThread() is often easier to read.

Fix Android UI thread access with Handler and main Looper

A Handler connected to Looper.getMainLooper() can also post UI work to the main thread. This approach is useful when the UI update is triggered from a helper class that does not directly call an Activity method.

</>
Copy
val mainHandler = Handler(Looper.getMainLooper())

Thread {
    val message = "Updated using Handler"

    mainHandler.post {
        binding.textviewMsg.text = message
    }
}.start()

When using this approach, make sure you import android.os.Handler and android.os.Looper.

</>
Copy
import android.os.Handler
import android.os.Looper

Fix CalledFromWrongThreadException with Kotlin coroutines

In apps that use Kotlin coroutines, keep blocking or CPU-heavy work on a background dispatcher, then switch back to Dispatchers.Main before touching views. In an Activity or Fragment, lifecycleScope is commonly used so the coroutine is tied to the lifecycle.

</>
Copy
lifecycleScope.launch {
    val message = withContext(Dispatchers.Default) {
        // Background work
        "Updated using coroutines"
    }

    // lifecycleScope.launch runs on Dispatchers.Main by default
    binding.textviewMsg.text = message
}

If you launch from a background dispatcher, switch explicitly to Dispatchers.Main for the view update.

</>
Copy
lifecycleScope.launch(Dispatchers.IO) {
    val message = "Loaded from background work"

    withContext(Dispatchers.Main) {
        binding.textviewMsg.text = message
    }
}

What Android view hierarchy means in this exception

A view hierarchy is the tree of UI objects created from your layout. For example, an Activity layout may contain a root LinearLayout, a nested TextView, a Button, and other child views. The thread that creates and attaches this hierarchy is normally the main thread.

When the exception says, Only the original thread that created a view hierarchy can touch its views, it means that the view tree must be accessed from the same UI thread that owns it. A background thread can calculate values, load data, or make network calls, but it should not directly call view methods such as setText(), setVisibility(), requestLayout(), or notifyDataSetChanged().

Main thread, background thread, process, and thread in Android

An Android process is an operating-system container for your app code and memory. A thread is an execution path inside that process. Every Android app starts with a main thread, and you may create additional worker threads for long-running tasks.

The main thread should stay responsive because it handles UI drawing and user input. Worker threads are useful for operations such as file processing, database work, image processing, and network requests. The safe pattern is to do the expensive work on a worker thread and return only the UI change to the main thread.

Common places where this Android thread exception happens

  • Updating a TextView after a network request completes on a background thread.
  • Changing ProgressBar progress from a manually created Thread.
  • Calling RecyclerView.Adapter.notifyDataSetChanged() from a worker thread.
  • Showing or dismissing a dialog from a callback that is not running on the main thread.
  • Changing view visibility after a database or file operation completes.

Checklist to avoid CalledFromWrongThreadException in Android

  • Do not update Android views directly from Thread, Executor, or background callbacks.
  • Use runOnUiThread() when the update belongs to an Activity.
  • Use View.post() when the update is specific to one view.
  • Use Handler(Looper.getMainLooper()) when posting from helper classes.
  • Use Dispatchers.Main when updating views from Kotlin coroutines.
  • Keep expensive work outside the main thread, and keep UI work on the main thread.
  • Check that the Activity or Fragment is still active before updating UI after a delayed operation.

CalledFromWrongThreadException FAQs

Which original thread created a view hierarchy can touch its view?

In most Android apps, the main thread creates the Activity or Fragment view hierarchy. Therefore, the main thread is the only thread that should directly update those views.

Can a background thread update a TextView in Android?

No. A background thread should not update a TextView directly. Prepare the value in the background thread, then update the TextView using runOnUiThread(), View.post(), Handler(Looper.getMainLooper()), or Dispatchers.Main.

What is the default thread in Android?

The default thread for an Android app’s UI work is the main thread, also called the UI thread. It handles drawing views, dispatching input events, and running many app callbacks.

Is runOnUiThread() the only fix for CalledFromWrongThreadException?

No. runOnUiThread() is a common Activity-based fix, but View.post(), Handler(Looper.getMainLooper()), and Kotlin coroutines with Dispatchers.Main can also be used depending on the structure of your code.

Why should long-running work not run on the Android main thread?

The main thread handles UI drawing and user input. If long-running work blocks it, the app may freeze or become unresponsive. Use a background thread for the work and return to the main thread only for the UI update.

Conclusion

In this Kotlin Android Tutorial, we have learnt how to fix Android Exception CalledFromWrongThreadException : Only the original thread that created a view hierarchy can touch its views. The rule is to keep background work off the main thread, but always move Android view updates back to the UI thread before touching the view hierarchy.