-1

I was experimenting with the AsyncTask and found an unusual scenario, here is my code.

class MainActivity : AppCompatActivity() {
    lateinit var textView:TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView = findViewById(R.id.textView)
        val task = MyAsyncTask()
        task.execute()
    }

    inner class MyAsyncTask:AsyncTask<Void,Void,String>() {
        override fun doInBackground(vararg params: Void?): String {
            //Thread.sleep(3000)
            textView.text ="From AsyncTask"
            return "hello"
        }
    }
}

It worked!!, see the Thread.sleep is commented but if I uncomment it then the usual error what we know

Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Why is so, if anybody know please share your feedback. Thanks

Lalit Behera
  • 534
  • 8
  • 18

3 Answers3

0

It's about the timing. When you comment Thread.sleep(3000), your view is not ready and connected with your activity, thus this version of code just updates a view that is yet to exist in UI.

However, after some time passes, UI would be started and when you update your view in doInBackground(), you will receive the exception that states Only the original thread that created a view hierarchy can touch its views. This also justifies the exception you got when you uncomment Thread.sleep(3000)

Onur A.
  • 3,007
  • 3
  • 22
  • 37
  • don't you think, if the view is not present it will throw null pointer exception? I think view is already created in the onCreate(). – Lalit Behera Feb 20 '19 at 07:06
  • 1
    No. Actually, view is created but it's not binded to UI yet, so it assumes the view is created by background thread(AsynTask in this case) rather than UI thread. – Onur A. Feb 20 '19 at 07:08
0

because when you're calling Thread.sleep in the following code:

inner class MyAsyncTask:AsyncTask<Void,Void,String>() {
    override fun doInBackground(vararg params: Void?): String {

        Thread.sleep(3000)
        textView.text ="From AsyncTask"
        ...
    }
}

it will run on current thread, which is a background thread of AsyncTask. You can see that in the Thread.sleep documentation:

public static void sleep (long millis, int nanos)

Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

So, the next code will switch to the background thread too:

textView.text ="From AsyncTask"

which will raise the exception.

ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
-1

As the exception clearly says :

Only the original thread that created a view hierarchy can touch its views.

AsyncTask doInBackground runs in separate background thread which don't have nothing to do with Main Thread now all the UI related work should be done on Main thread so rather then settext on doInBackground do it in onpostexecute.

Kapil Rajput
  • 11,429
  • 9
  • 50
  • 65