Android报”WrongThreadException”如何解决?

  • Post category:Android

当在Android App的非UI线程中执行UI更新操作时,就会抛出WrongThreadException异常。该异常的原因是UI更新应该是在UI线程中完成的,而Android系统又是单线程模型的,意味着只有UI线程有权访问UI组件。因此,当想要更新UI组件内容时,必须确保这个更新操作是在UI线程中执行的。

下面是两个示例说明,解释WrongThreadException异常的原因和如何解决:

示例一:

new Thread(new Runnable() {
    @Override
    public void run() {
        // 在非UI线程中执行以下操作
        TextView textView = findViewById(R.id.text_view);
        textView.setText("Hello World!"); // 抛出WrongThreadException
    }
}).start();

在这个示例中,我们在一个新的线程中更新了UI组件TextView的内容,但是由于我们在非UI线程中执行了UI更新操作,导致抛出了WrongThreadException异常。

为了解决这个问题,我们可以使用Android提供的Handler类,在UI线程中执行我们想要更新的UI操作。修改代码如下:

new Thread(new Runnable() {
    @Override
    public void run() {
        // 在非UI线程中执行以下操作
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                TextView textView = findViewById(R.id.text_view);
                textView.setText("Hello World!");
            }
        });
    }
}).start();

在这个示例中,我们创建了一个Handler对象,在它的post()方法中创建了一个新的Runnable对象,用于在UI线程中执行UI更新操作。这样我们就避免了在非UI线程中直接更新UI组件引起的异常。

示例二:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn = findViewById(R.id.button);

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在监听器中的非UI线程中执行以下操作
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 在非UI线程中执行以下操作
                    TextView textView = findViewById(R.id.text_view);
                    textView.setText("Hello World!"); // 抛出WrongThreadException
                }
            }).start();
        }
    });
}

在这个示例中,我们在OnClickListener的回调方法中创建了一个新的线程,用于更新UI组件。由于该回调方法运行在UI线程中,但是更新UI组件的线程是一个新的非UI线程,又会引发WrongThreadException异常。

为了解决这个问题,我们可以使用和上述示例一样的方法,在新线程中使用Handler在UI线程中执行UI更新操作。代码修改如下:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn = findViewById(R.id.button);

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 在监听器中的非UI线程中执行以下操作
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 在非UI线程中执行以下操作
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            TextView textView = findViewById(R.id.text_view);
                            textView.setText("Hello World!");
                        }
                    });
                }
            }).start();
        }
    });
}

在这个示例中,我们使用了和上面的方法一样的方式,将UI更新操作放到了Handler的post()方法中,在UI线程中执行更新操作,避免了在非UI线程中更新UI组件引起的异常。