0

1.我有一个关于在子线程中创建处理程序的问题

喜欢

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();
}

上面的代码会崩溃。

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.我知道要在主线程中更新ui,handler在主线程中创建,然后在子线程中发送消息给handler就可以更新ui了。

3.我的问题是子线程中创建的处理程序的作用是什么?我们什么时候需要这样做?场景有什么用?

希望有人能解决我的困惑!</p>

4

2 回答 2

1
  1. 我在子线程中创建处理程序时遇到问题。

您正在从后台线程更新 ui。

例如,您可以从线程发送消息并更新 ui

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);
    }
};

接着

  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();

或者,如果您只是想要延迟,则不需要线程,循环器和睡眠,如 pskink https://developer.android.com/reference/android/os/Handler.html的评论中所述

  1. 我知道要在主线程中更新ui,在主线程中创建handler创建,然后在子线程中发送消息给handler就可以更新ui了。

是的,您是对的,您可以在 ui 线程上创建处理程序,您可以从线程发送消息并更新您的 ui

  1. 我的问题是在子线程中创建的处理程序的作用是什么?

Handler 与线程的 looper 相关联。如果您在 ui 线程中有一个处理程序,则它与之关联。在您的情况下,您将它放在一个线程中,因此处理程序与该线程循环器相关联。

我们什么时候需要这样做?场景有什么用?

当您想从后台线程到 ui 线程或从 ui 线程到后台线程进行通信时。

于 2017-09-11T15:11:16.100 回答
0

你的代码

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();

可以重写以使用 Android api:

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

另请注意,您的主要问题是您在已经位于工作线程中的 Runnable 中创建 Handler,您也可以在 onCreate 早期创建它。

于 2017-09-11T16:30:37.397 回答