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

You need to observe UI calls on the main thread using AndroidSchedulers.mainThread().

Show
override fun OnUserNumberClicked(photo: UserPicture) { subscriptions.add( mRepository.userPicture() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { userListener.updateUserNumber() } ) }

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

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

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00

762

I've built a simple music player in Android. anycodings_multithreading The view for each song contains a SeekBar, anycodings_multithreading implemented like this:

public class Song extends Activity implements OnClickListener,Runnable { private SeekBar progress; private MediaPlayer mp; // ... private ServiceConnection onService = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder rawBinder) { appService = ((MPService.LocalBinder)rawBinder).getService(); // service that handles the MediaPlayer progress.setVisibility(SeekBar.VISIBLE); progress.setProgress(0); mp = appService.getMP(); appService.playSong(title); progress.setMax(mp.getDuration()); new Thread(Song.this).start(); } public void onServiceDisconnected(ComponentName classname) { appService = null; } }; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.song); // ... progress = (SeekBar) findViewById(R.id.progress); // ... } public void run() { int pos = 0; int total = mp.getDuration(); while (mp != null && pos<total) { try { Thread.sleep(1000); pos = appService.getSongPosition(); } catch (InterruptedException e) { return; } catch (Exception e) { return; } progress.setProgress(pos); } }

This works fine. Now I want a timer counting anycodings_multithreading the seconds/minutes of the progress of the anycodings_multithreading song. So I put a TextView in the layout, get anycodings_multithreading it with findViewById() in onCreate(), and anycodings_multithreading put this in run() after anycodings_multithreading progress.setProgress(pos):

String time = String.format("%d:%d", TimeUnit.MILLISECONDS.toMinutes(pos), TimeUnit.MILLISECONDS.toSeconds(pos), TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes( pos)) ); currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);

But that last line gives me the exception:

android.view.ViewRoot$CalledFromWrongThreadException: anycodings_multithreading Only the original thread that created a view anycodings_multithreading hierarchy can touch its views.

Yet I'm doing basically the same thing here anycodings_multithreading as I'm doing with the SeekBar - creating the anycodings_multithreading view in onCreate, then touching it in run() anycodings_multithreading - and it doesn't give me this complaint.

Total Answers 30

27

Answers 1 : of Android Only the original thread that created a view hierarchy can touch its views.

You have to move the portion of the anycodings_multithreading background task that updates the UI onto anycodings_multithreading the main thread. There is a simple piece anycodings_multithreading of code for this:

runOnUiThread(new Runnable() { @Override public void run() { // Stuff that updates the UI } });

Documentation for anycodings_multithreading Activity.runOnUiThread.

Just nest this inside the method that is anycodings_multithreading running in the background, and then copy anycodings_multithreading paste the code that implements any anycodings_multithreading updates in the middle of the block. anycodings_multithreading Include only the smallest amount of code anycodings_multithreading possible, otherwise you start to defeat anycodings_multithreading the purpose of the background thread.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

mRahman

3

Answers 2 : of Android Only the original thread that created a view hierarchy can touch its views.

I solved this by putting runOnUiThread( anycodings_multithreading new Runnable(){ .. inside run():

thread = new Thread(){ @Override public void run() { try { synchronized (this) { wait(5000); runOnUiThread(new Runnable() { @Override public void run() { dbloadingInfo.setVisibility(View.VISIBLE); bar.setVisibility(View.INVISIBLE); loadingText.setVisibility(View.INVISIBLE); } }); } } catch (InterruptedException e) { e.printStackTrace(); } Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class); startActivity(mainActivity); }; }; thread.start();

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

1

Answers 3 : of Android Only the original thread that created a view hierarchy can touch its views.

My solution to this:

private void setText(final TextView text,final String value){ runOnUiThread(new Runnable() { @Override public void run() { text.setText(value); } }); }

Call this method on a background thread.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

4

Answers 4 : of Android Only the original thread that created a view hierarchy can touch its views.

Kotlin coroutines can make your code anycodings_multithreading more concise and readable like this:

MainScope().launch { withContext(Dispatchers.Default) { //TODO("Background processing...") } TODO("Update UI here!") }

Or vice versa:

GlobalScope.launch { //TODO("Background processing...") withContext(Dispatchers.Main) { // TODO("Update UI here!") } TODO("Continue background processing...") }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

4

Answers 5 : of Android Only the original thread that created a view hierarchy can touch its views.

Usually, any action involving the user anycodings_multithreading interface must be done in the main or UI anycodings_multithreading thread, that is the one in which anycodings_multithreading onCreate() and event handling are anycodings_multithreading executed. One way to be sure of that is anycodings_multithreading using runOnUiThread(), another is using anycodings_multithreading Handlers.

ProgressBar.setProgress() has a anycodings_multithreading mechanism for which it will always anycodings_multithreading execute on the main thread, so that's anycodings_multithreading why it worked.

See Painless Threading.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

jidam

3

Answers 6 : of Android Only the original thread that created a view hierarchy can touch its views.

I've been in this situation, but I found anycodings_multithreading a solution with the Handler Object.

In my case, I want to update a anycodings_multithreading ProgressDialog with the observer anycodings_multithreading pattern. My view implements observer and anycodings_multithreading overrides the update method.

So, my main thread create the view and anycodings_multithreading another thread call the update method anycodings_multithreading that update the ProgressDialop and....:

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

It's possible to solve the problem with anycodings_multithreading the Handler Object.

Below, different parts of my code:

public class ViewExecution extends Activity implements Observer{ static final int PROGRESS_DIALOG = 0; ProgressDialog progressDialog; int currentNumber; public void onCreate(Bundle savedInstanceState) { currentNumber = 0; final Button launchPolicyButton = ((Button) this.findViewById(R.id.launchButton)); launchPolicyButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(PROGRESS_DIALOG); } }); } @Override protected Dialog onCreateDialog(int id) { switch(id) { case PROGRESS_DIALOG: progressDialog = new ProgressDialog(this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("Loading"); progressDialog.setCancelable(true); return progressDialog; default: return null; } } @Override protected void onPrepareDialog(int id, Dialog dialog) { switch(id) { case PROGRESS_DIALOG: progressDialog.setProgress(0); } } // Define the Handler that receives messages from the thread and update the progress final Handler handler = new Handler() { public void handleMessage(Message msg) { int current = msg.arg1; progressDialog.setProgress(current); if (current >= 100){ removeDialog (PROGRESS_DIALOG); } } }; // The method called by the observer (the second thread) @Override public void update(Observable obs, Object arg1) { Message msg = handler.obtainMessage(); msg.arg1 = ++currentPluginNumber; handler.sendMessage(msg); } }

This explanation can be found on this anycodings_multithreading page, and you must read the "Example anycodings_multithreading ProgressDialog with a second thread".

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

3

Answers 7 : of Android Only the original thread that created a view hierarchy can touch its views.

You can use Handler to Delete View anycodings_multithreading without disturbing the main UI anycodings_multithreading Thread. Here is example code

new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { //do stuff like remove view etc adapter.remove(selecteditem); } });

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

5

Answers 8 : of Android Only the original thread that created a view hierarchy can touch its views.

Kotlin Answer

We have to use UI Thread for the job anycodings_multithreading with true way. We can use UI Thread in anycodings_multithreading Kotlin, such as:

runOnUiThread(Runnable { //TODO: Your job is here..! })

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

3

Answers 9 : of Android Only the original thread that created a view hierarchy can touch its views.

I see that you have accepted anycodings_multithreading @providence's answer. Just in case, you anycodings_multithreading can also use the handler too! First, do anycodings_multithreading the int fields.

private static final int SHOW_LOG = 1; private static final int HIDE_LOG = 0;

Next, make a handler instance as a anycodings_multithreading field.

//TODO __________[ Handler ]__________ @SuppressLint("HandlerLeak") protected Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // Put code here... // Set a switch statement to toggle it on or off. switch(msg.what) { case SHOW_LOG: { ads.setVisibility(View.VISIBLE); break; } case HIDE_LOG: { ads.setVisibility(View.GONE); break; } } } };

Make a method.

//TODO __________[ Callbacks ]__________ @Override public void showHandler(boolean show) { handler.sendEmptyMessage(show ? SHOW_LOG : HIDE_LOG); }

Finally, put this at onCreate() method.

showHandler(true);

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

1

Answers 10 : of Android Only the original thread that created a view hierarchy can touch its views.

Use this code, and no need to anycodings_multithreading runOnUiThread function:

private Handler handler; private Runnable handlerTask; void StartTimer(){ handler = new Handler(); handlerTask = new Runnable() { @Override public void run() { // do something textView.setText("some text"); handler.postDelayed(handlerTask, 1000); } }; handlerTask.run(); }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

1

Answers 11 : of Android Only the original thread that created a view hierarchy can touch its views.

I had a similar issue, and my solution anycodings_multithreading is ugly, but it works:

void showCode() { hideRegisterMessage(); // Hides view final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { showRegisterMessage(); // Shows view } }, 3000); // After 3 seconds }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

jidam

1

Answers 12 : of Android Only the original thread that created a view hierarchy can touch its views.

I was facing a similar problem and none anycodings_multithreading of the methods mentioned above worked anycodings_multithreading for me. In the end, this did the trick anycodings_multithreading for me:

Device.BeginInvokeOnMainThread(() => { myMethod(); });

I found this gem here.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

6

Answers 13 : of Android Only the original thread that created a view hierarchy can touch its views.

I use Handler with anycodings_multithreading Looper.getMainLooper(). It worked fine anycodings_multithreading for me.

Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { // Any UI task, example textView.setText("your text"); } }; handler.sendEmptyMessage(1);

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

3

Answers 14 : of Android Only the original thread that created a view hierarchy can touch its views.

This is explicitly throwing an error. It anycodings_multithreading says whichever thread created a view, anycodings_multithreading only that can touch its views. It is anycodings_multithreading because the created view is inside that anycodings_multithreading thread's space. The view creation (GUI) anycodings_multithreading happens in the UI (main) thread. So, you anycodings_multithreading always use the UI thread to access those anycodings_multithreading methods.

In the above picture, the progress anycodings_multithreading variable is inside the space of the UI anycodings_multithreading thread. So, only the UI thread can anycodings_multithreading access this variable. Here, you're anycodings_multithreading accessing progress via new Thread(), and anycodings_multithreading that's why you got an error.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

2

Answers 15 : of Android Only the original thread that created a view hierarchy can touch its views.

This happened to my when I called for an anycodings_multithreading UI change from a doInBackground from anycodings_multithreading Asynctask instead of using anycodings_multithreading onPostExecute.

Dealing with the UI in onPostExecute anycodings_multithreading solved my problem.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

1

Answers 16 : of Android Only the original thread that created a view hierarchy can touch its views.

I was working with a class that did not anycodings_multithreading contain a reference to the context. So anycodings_multithreading it was not possible for me to use anycodings_multithreading runOnUIThread(); I used view.post(); and anycodings_multithreading it was solved.

timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { final int currentPosition = mediaPlayer.getCurrentPosition(); audioMessage.seekBar.setProgress(currentPosition / 1000); audioMessage.tvPlayDuration.post(new Runnable() { @Override public void run() { audioMessage.tvPlayDuration.setText(ChatDateTimeFormatter.getDuration(currentPosition)); } }); } }, 0, 1000);

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

6

Answers 17 : of Android Only the original thread that created a view hierarchy can touch its views.

When using AsyncTask Update the UI in anycodings_multithreading onPostExecute method

@Override protected void onPostExecute(String s) { // Update UI here }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

5

Answers 18 : of Android Only the original thread that created a view hierarchy can touch its views.

This is the stack trace of mentioned anycodings_multithreading exception

at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6149) at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:843) at android.view.View.requestLayout(View.java:16474) at android.view.View.requestLayout(View.java:16474) at android.view.View.requestLayout(View.java:16474) at android.view.View.requestLayout(View.java:16474) at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352) at android.view.View.requestLayout(View.java:16474) at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352) at android.view.View.setFlags(View.java:8938) at android.view.View.setVisibility(View.java:6066)

So if you go and dig then you come to anycodings_multithreading know

void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }

Where mThread is initialize in anycodings_multithreading constructor like below

mThread = Thread.currentThread();

All I mean to say that when we created anycodings_multithreading particular view we created it on UI anycodings_multithreading Thread and later try to modifying in a anycodings_multithreading Worker Thread.

We can verify it via below code snippet

Thread.currentThread().getName()

when we inflate layout and later where anycodings_multithreading you are getting exception.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

joy

3

Answers 19 : of Android Only the original thread that created a view hierarchy can touch its views.

If you do not want to use runOnUiThread anycodings_multithreading API, you can in fact implement AsynTask anycodings_multithreading for the operations that takes some anycodings_multithreading seconds to complete. But in that case, anycodings_multithreading also after processing your work in anycodings_multithreading doinBackground(), you need to return the anycodings_multithreading finished view in onPostExecute(). The anycodings_multithreading Android implementation allows only main anycodings_multithreading UI thread to interact with views.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

5

Answers 20 : of Android Only the original thread that created a view hierarchy can touch its views.

For a one-liner version of the anycodings_multithreading runOnUiThread() approach, you can use a anycodings_multithreading lambda function, i.e.:

runOnUiThread(() -> doStuff(Object, myValue));

where doStuff() can represents some anycodings_multithreading method used to modify the value of some anycodings_multithreading UI Object (setting text, changing anycodings_multithreading colors, etc.).

I find this to be much neater when anycodings_multithreading trying to update several UI objects anycodings_multithreading without the need for a 6 line Runnable anycodings_multithreading definition at each as mentioned in the anycodings_multithreading most upvoted answer, which is by no anycodings_multithreading means incorrect, it just takes up a lot anycodings_multithreading more space and I find to be less anycodings_multithreading readable.

So this:

runOnUiThread(new Runnable() { @Override public void run() { doStuff(myTextView, "myNewText"); } });

can become this:

runOnUiThread(() -> doStuff(myTextView, "myNewText"));

where the definition of doStuff lies anycodings_multithreading elsewhere.

Or if you don't need to be so anycodings_multithreading generalizable, and just need to set the anycodings_multithreading text of a TextView object:

runOnUiThread(() -> myTextView.setText("myNewText"));

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

4

Answers 21 : of Android Only the original thread that created a view hierarchy can touch its views.

If you simply want to invalidate (call anycodings_multithreading repaint/redraw function) from your non anycodings_multithreading UI Thread, use postInvalidate()

myView.postInvalidate();

This will post an invalidate request on anycodings_multithreading the UI-thread.

For more information : anycodings_multithreading what-does-postinvalidate-do

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

5

Answers 22 : of Android Only the original thread that created a view hierarchy can touch its views.

Well, You can do it like this.

https://developer.android.com/reference/android/view/View#post(java.lang.Runnable)

A simple approach

currentTime.post(new Runnable(){ @Override public void run() { currentTime.setText(time); } }

it also provides delay

https://developer.android.com/reference/android/view/View#postDelayed(java.lang.Runnable,%20long)

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

3

Answers 23 : of Android Only the original thread that created a view hierarchy can touch its views.

For me the issue was that I was calling anycodings_multithreading onProgressUpdate() explicitly from my anycodings_multithreading code. This shouldn't be done. I called anycodings_multithreading publishProgress() instead and that anycodings_multithreading resolved the error.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

6

Answers 24 : of Android Only the original thread that created a view hierarchy can touch its views.

In my case, I have EditText in Adaptor, anycodings_multithreading and it's already in the UI thread. anycodings_multithreading However, when this Activity loads, it's anycodings_multithreading crashes with this error.

My solution is I need to remove anycodings_multithreading <requestFocus /> out from EditText anycodings_multithreading in XML.

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

5

Answers 25 : of Android Only the original thread that created a view hierarchy can touch its views.

For the people struggling in Kotlin, it anycodings_multithreading works like this:

lateinit var runnable: Runnable //global variable runOnUiThread { //Lambda runnable = Runnable { //do something here runDelayedHandler(5000) } } runnable.run() //you need to keep the handler outside the runnable body to work in kotlin fun runDelayedHandler(timeToWait: Long) { //Keep it running val handler = Handler() handler.postDelayed(runnable, timeToWait) }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

1

Answers 26 : of Android Only the original thread that created a view hierarchy can touch its views.

If you couldn't find a UIThread you can anycodings_multithreading use this way .

yourcurrentcontext mean, you need to anycodings_multithreading parse Current Context

new Thread(new Runnable() { public void run() { while (true) { (Activity) yourcurrentcontext).runOnUiThread(new Runnable() { public void run() { Log.d("Thread Log","I am from UI Thread"); } }); try { Thread.sleep(1000); } catch (Exception ex) { } } } }).start();

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

5

Answers 27 : of Android Only the original thread that created a view hierarchy can touch its views.

If you are within a fragment, then you anycodings_multithreading also need to get the activity object as anycodings_multithreading runOnUIThread is a method on the anycodings_multithreading activity.

An example in Kotlin with some anycodings_multithreading surrounding context to make it clearer - anycodings_multithreading this example is navigating from a camera anycodings_multithreading fragment to a gallery fragment:

// Setup image capture listener which is triggered after photo has been taken imageCapture.takePicture( outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback { override fun onError(exc: ImageCaptureException) { Log.e(TAG, "Photo capture failed: ${exc.message}", exc) } override fun onImageSaved(output: ImageCapture.OutputFileResults) { val savedUri = output.savedUri ?: Uri.fromFile(photoFile) Log.d(TAG, "Photo capture succeeded: $savedUri") //Do whatever work you do when image is saved //Now ask navigator to move to new tab - as this //updates UI do on the UI thread activity?.runOnUiThread( { Navigation.findNavController( requireActivity(), R.id.fragment_container ).navigate(CameraFragmentDirections .actionCameraToGallery(outputDirectory.absolutePath)) })

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

3

Answers 28 : of Android Only the original thread that created a view hierarchy can touch its views.

For anyone using fragment:

(context as Activity).runOnUiThread { //TODO }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

raja

4

Answers 29 : of Android Only the original thread that created a view hierarchy can touch its views.

Solved : Just put this method in anycodings_multithreading doInBackround Class... and pass the anycodings_multithreading message

public void setProgressText(final String progressText){ Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { // Any UI task, example progressDialog.setMessage(progressText); } }; handler.sendEmptyMessage(1); }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

miraj

5

Answers 30 : of Android Only the original thread that created a view hierarchy can touch its views.

In my case, the caller calls too many anycodings_multithreading times in short time will get this error, anycodings_multithreading I simply put elapsed time checking to do anycodings_multithreading nothing if too short, e.g. ignore if anycodings_multithreading function get called less than 0.5 anycodings_multithreading second:

private long mLastClickTime = 0; public boolean foo() { if ( (SystemClock.elapsedRealtime() - mLastClickTime) < 500) { return false; } mLastClickTime = SystemClock.elapsedRealtime(); //... do ui update }

0

2022-08-04T23:30:11+00:00 2022-08-04T23:30:11+00:00Answer Link

jidam

How do you fix only the original thread that created a view hierarchy can touch its views?

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

What is difference between thread and coroutines?

Coroutines are very similar to threads. However, coroutines are cooperatively multitasked, whereas threads are typically preemptively multitasked. Coroutines provide concurrency but not parallelism.

Does coroutine run on main thread?

On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.

Does coroutine create new thread?

The launch function is a coroutine builder that starts a new coroutine without blocking the current thread and returns a reference to the coroutine as a Job object: runBlocking { val job = launch(Dispatchers.