19

I am tring to setText in another thread, that is, child thread. But for the following code, it is giving the error

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

 

 

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    img = (ImageView)findViewById(R.id.img);
    pb = (ProgressBar)findViewById(R.id.pb);
    this.tv = (TextView)findViewById(R.id.perc);
    tv.setText("30 %");
    pb.setProgress(30);
    pb.setMax(100);
}

public void set(int p)
{
    tv.setText(p + " %");
}

protected void onStart()
{
    super.onStart();
    pb.setProgress(20);

    Thread t = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            try {
                int i = pb.getProgress();
                while(i <100)
                {
                    while(pb.getProgress()<100)
                    {
                        pb.incrementProgressBy(5);
                        Thread.sleep(1000);
                    }
                i+=10;
                pb.setProgress(i);
                Thread.interrupted();
                set(i);
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    });
    t.start();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ravi Ranjan
  • 526
  • 2
  • 6
  • 15

4 Answers4

62

You need a reference to that textview and then do:

textView.post(new Runnable() {
    public void run() {
        textView.setText(yourText);
    } 
});

in Kotlin:

val textView: TextView = findViewById(R.id.textView)
textView.post(Runnable { textView.setText(yourText) })
nacho1111
  • 73
  • 1
  • 8
Bondax
  • 3,143
  • 28
  • 35
  • Thanks this worked. I just want to know that this is creating new child thread of working in UI(parent thread). – Ravi Ranjan Mar 27 '12 at 06:42
  • @LoungeKatt There is only one UI-Thread. `View.post` uses the Handler, while `Context.runOnUiThread` checks, if the calling thread is the ui thread and posts to Handler, otherwise. – Bondax Mar 26 '18 at 07:54
  • @LoungeKatt I had to giggle when I read that you think taking "separate UI thread" as something different than "separate reference" is "taking it too literally" – Bondax Mar 27 '18 at 08:09
  • @Bondax Glad something made you laugh. It sounds like you take yourself entirely too seriously. If you need the whole thing explained using appropriate wording and clear examples, you should probably start a separate question. – Abandoned Cart Mar 27 '18 at 08:42
  • https://stackoverflow.com/a/10558238/461982 To avoid confusion for later viewers: the key difference is that `runOnUiThread` may still cause an `android.view.ViewRoot$CalledFromWrongThreadException` while `post` will maintain the specific reference to the view being edited. Hopefully this wording is clear enough for you ;) – Abandoned Cart Mar 27 '18 at 08:48
  • Tbis answer helped a lot I was getting lines of text in runnable, for read more /read less. Works fine in latest devices, but gave textview must not null on 21 api. I AM DOING textview.Layout.Getlines – MRamzan Dec 25 '20 at 06:40
11

Use runOnUiThread for updating the UI control. In your case:

runningActivity.runOnUiThread(new Runnable() {
    public void run() {
        tv.setText(p + " %");
    }
});

Edited:

Activity mActivity;
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mActivity= this;
   ...
   ..//The rest of the code
} //close oncreate()

thread{
    mActivity.runOnUiThread(new Runnable() {
        public void run() {
            tv.setText(p + " %");
        }
    });
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mohammed Azharuddin Shaikh
  • 41,633
  • 14
  • 96
  • 115
2

You can use handle :

handler.post(new Runnable() {
    public void run() {
        textView.setText(yourText);
    }
});

But your textView and yourText must be class fields.

In your thread (activity) where you create textView use:

Handler handler = new Handler();

And pass handler into another thread.

bigspawn
  • 1,727
  • 3
  • 16
  • 16
2

Either you can use runOnUiThread or use Handler to set text in TextView.

Mohammed Azharuddin Shaikh
  • 41,633
  • 14
  • 96
  • 115
Richa
  • 3,165
  • 1
  • 22
  • 26