1

When I want to setText to a textView, the application force closes and gives me this error:

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

This is a part of my code :

Thread ThreadRecording = new Thread(new Runnable() {
    public void run() {
        while(recorder)
        {
            if (body_num = 10)
            {
                TextView loog = (TextView)findViewById(R.id.textView1);
                loog.setText("Total : 10, Thank you");
            }
        }
    }
});
ThreadRecording.start();

There's a button; if the user clicks it, it calls a function to set body_num = body_num + 1 and the thread checks if body_num == 10

Gary
  • 13,303
  • 18
  • 49
  • 71
Jeff Bic
  • 546
  • 1
  • 6
  • 15
  • refer here http://stackoverflow.com/questions/5161951/android-only-the-original-thread-that-created-a-view-hierarchy-can-touch-its-vi – Androyds Dec 27 '12 at 00:53
  • (A duplicate/solution would have been found if merely searching for the error message. Try it in the future.) –  Dec 27 '12 at 01:54
  • Two notes: 1 - `ThreadRecording` is an instance of the class `Thread`, and as such should have its name start with a lowercase letter IE `threadRecording`. 2 - You could skip declaring the `Thread` and instead just have `new Thread(new Rubbable() { /* contents... */ } ).start();` – ArtOfWarfare Dec 27 '12 at 02:06

3 Answers3

3

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

Because just only with UI (main) thread, are you able to manipulate views. You can use Hanlder to update your views.

There are two main uses for a Handler:

  1. To schedule messages and runnables to be executed as some point in the future; and
  2. To enqueue an action to be performed on a different thread than your own. When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate."
    -- from "developer.android.com"

Example:

Backgroud thread:

new Thread() {

public void run() {
    while(recorder)
        {
            if (body_num = 10)
            {                
                messageHandler.sendEmptyMessage(0);
            }
        }
   }

}.start();

Your handler which is put in main thread:

private Handler messageHandler = new Handler() {

public void handleMessage(Message msg) {
             //update your view here
   }
};
Gary
  • 13,303
  • 18
  • 49
  • 71
secretlm
  • 2,361
  • 2
  • 27
  • 38
1

You can only modify views in UI thread, you need to use Handler, such as,

Handler h = new Handler(context.getMainLooper()) {
    public void handleMessage(Message msg) {
        TextView loog = (TextView)findViewById(R.id.textView1);
        loog.setText(msg.obj);
    }
};

Thread ThreadRecording = new Thread(new Runnable() {
    public void run() {
        while(recorder)
        {
            if (body_num = 10)
            {
                Message message = new Message();
                message.obj = "Total : 10, Thank you";
                handler.sendMessage(message);
            }
        }
    }
});
ThreadRecording.start();
Qiang Jin
  • 4,427
  • 19
  • 16
0

This can also be achieved by using a AsyncTask. Below is the example code by which a string resource (R.string.your_text) is set in a TextView:

public class CommonSetText extends AsyncTask<Void, Void, Integer> {
private WeakReference<TextView> textView;
private int stringID;

public CommonSetText ( TextView textView, Integer stringID) {
    this.textView = new WeakReference<>(textView);
    this.stringID = stringID;
}

@Override
protected Integer doInBackground ( Void... voids ) {
    return stringID;
}

@Override
protected void onPostExecute ( Integer stringID ) {
    super.onPostExecute ( stringID );
    textView.get ().setText ( stringID );
}
}

And the text is then set to text view using the below code:

new CommonSetText ( textView, R.string.your_text ).execute (  );
niranj1997
  • 719
  • 8
  • 16