Setting text on TextView from background thread anomaly

Viewed 1937

I've just started playing with Android Concurrency/Loopers/Handers, and I have just faced with strange anomaly. The code below doesn't block me from setting text on TextView from different Thread.

TextView tv;
Handler backgroundHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tv = (TextView) findViewById(R.id.sample_text);
    Runnable run = new Runnable() {
        @Override
        public void run() {
            Looper.prepare();
            backgroundHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    String text = (String) msg.obj;
                    tv.setText(Thread.currentThread().getName() + " " + text);
                }
            };
            Looper.loop();
        }
    };

    Thread thread = new Thread(run);
    thread.setName("Background thread");
    thread.start();
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Message message = backgroundHandler.obtainMessage();
    message.obj = "message from UI";
    backgroundHandler.sendMessage(message);
}

And guess what happen

enter image description here

But, when I sleep background thread for a while

backgroundHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String text = (String) msg.obj;
                tv.setText(Thread.currentThread().getName() + " " + text);
            }
        };

it does throw exception as I expected

07-03 18:54:40.506 5996-6025/com.stasbar.tests E/AndroidRuntime: FATAL EXCEPTION: Background thread
                                                             Process: com.stasbar.tests, PID: 5996
                                                             android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                 at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7275)

Can someone explain me what happened ? Why I was able to set text from different thread ?

2 Answers
Related