What is the role of the child thread creation handler?

812 views Asked by At

1.I have a problem about creating a handler in a child thread

like

public class Main4Activity extends Activity {

private TextView mTextView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = (TextView) findViewById(R.id.text_view);
    new Thread() {
        @Override
        public void run() {
            Looper.prepare();
            @SuppressLint("HandlerLeak") Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Toast.makeText(Main4Activity.this, "handler msg", Toast.LENGTH_SHORT).show();
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mTextView.setText("100");
                }
            };
            handler.sendEmptyMessage(1);
            Looper.loop();
        }
    }.start();
}

} The above code will crash.

Process: com.example.hellokai.kotlindemo, PID: 27485
                                               android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                   at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6986)
                                                   at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1074)
                                                   at android.view.View.requestLayout(View.java:19889)
                                                   at android.view.View.requestLayout(View.java:19889)
                                                   at android.view.View.requestLayout(View.java:19889)
                                                   at android.view.View.requestLayout(View.java:19889)
                                                   at android.support.constraint.ConstraintLayout.requestLayout(ConstraintLayout.java:1959)
                                                   at android.view.View.requestLayout(View.java:19889)
                                                   at android.widget.TextView.checkForRelayout(TextView.java:7369)
                                                   at android.widget.TextView.setText(TextView.java:4480)
                                                   at android.widget.TextView.setText(TextView.java:4337)
                                                   at android.widget.TextView.setText(TextView.java:4312)
                                                   at com.example.hellokai.kotlindemo.Main4Activity$1$1.handleMessage(Main4Activity.java:40)
                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                   at android.os.Looper.loop(Looper.java:154)
                                                   at com.example.hellokai.kotlindemo.Main4Activity$1.run(Main4Activity.java:45)

2.I know to update ui in the main thread,handler creation in the main thread to create, and then send a message in the child thread to the handler can update Ui.

3.My question is what is the role of the handler created in the child thread? When do we need to do that? What is the use of the scene?

Hope someone can solve my confusion!

2

There are 2 answers

6
Raghunandan On BEST ANSWER
  1. I have a problem about creating a handler in a child thread.

Your are updating ui from the background thread.

For Example you could send a message from a thread and update ui like

private Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        Toast.makeText(Main4Activity.this.getApplicationContext(), "handler msg", Toast.LENGTH_SHORT).show();

        mTextView.setText((String)msg.obj);
    }
};

and then

  new Thread() {
        @Override
        public void run() {

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Message msg = Message.obtain(); // Creates an new Message instance
            msg.obj = "Hello";
            handler.sendMessage(msg);

        }
    }.start();

Or If you just want a delay there is not need for a thread, looper and sleep as already noted in comments by pskink https://developer.android.com/reference/android/os/Handler.html

  1. I know to update ui in the main thread,handler creation in the main thread to create, and then send a message in the child thread to the handler can update Ui.

Yes your are right you can create the handler on the ui thread you can send message from the thread and update your ui

  1. My question is what is the role of the handler created in the child thread?

Handler is associated with a thread's looper. If you have a handler in ui thread its associated with it. In your case you have it inside a thread and hence handler is associated with that threads looper.

When do we need to do that? What is the use of the scene?

When you want to communicate from a backgroud thread to ui thread or from ui thread to background thread.

4
Marcos Vasconcelos On

Your code

new Thread() {
    @Override
    public void run() {
        Looper.prepare();
        @SuppressLint("HandlerLeak") Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Toast.makeText(Main4Activity.this, "handler msg", Toast.LENGTH_SHORT).show();
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mTextView.setText("100");
            }
        };
        handler.sendEmptyMessage(1);
        Looper.loop();
    }
}.start();

Can be rewrote to use Android apis:

new Handler(getMainLooper()).postDelayed(
new Runnable() {
    @Override
    public void run() {
                Toast.makeText(Main4Activity.this, "handler msg", Toast.LENGTH_SHORT).show();
                mTextView.setText("100");
        }
    }
}, 200);

Note also that your main problem is that you create the Handler inside the Runnable that already is in a worker-thread, you can also create it early in the onCreate.