赞
踩
在安卓开发中,大部分情况下是不能在子线程直接更新UI的,只能在UI线程更新UI,其根本原因在于加入在一个Activity中有多个线程去更新UI,且没有加锁机制,可能会产生界面混乱的情况,但是如果都加锁的话会导致性能下降。所以android提供了一套子线程更新UI的机制。在某些特殊的情况下是可以直接在子线程更新UI的。
布局界面只有一个textView
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.support.annotation.Nullable;
- import android.widget.TextView;
-
-
- public class HandlerActivity extends Activity {
-
-
- private TextView textView;
-
-
- @SuppressLint("HandlerLeak")
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
-
- textView.setText("okok");
- super.handleMessage(msg);
- }
- };
-
-
- //第一种 handler post runnable
- //其本质也是发送的一个message对象
- private void handler1() {
- handler.post(new Runnable() {
- @Override
- public void run() {
- textView.setText("ok");
- }
- });
- }
- //第二种 handler send message
- private void handler2() {
- handler.sendEmptyMessage(1);
- }
- //第三种 runOnUiThread
- private void updateUI(){
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- textView.setText("okokok");
- }
- });
- }
- //第四种 view post runnable
- private void viewUI(){
- textView.post(new Runnable() {
- @Override
- public void run() {
- textView.setText("okokokok");
- }
- });
- }
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handler);
- textView = findViewById(R.id.tv_handler);
-
-
- new Thread() {
- @Override
- public void run() {
- super.run();
- try {
- Thread.sleep(2000);
- //handler1();
- //handler2();
- //updateUI();
- viewUI();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }.start();
- }
- }
以上四种方式其本质其实都是通过handler发送message去通知UI线程更新UI
- public class ThreadActivity extends Activity {
-
- private TextView textView;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_handler);
- textView = findViewById(R.id.tv_handler);
-
- new Thread() {
- @Override
- public void run() {
- super.run();
- textView.setText("1111");
-
- //try {
- // Thread.sleep(2000);
- // textView.setText("1111");
-
- // } catch (InterruptedException e) {
- // e.printStackTrace();
- // }
-
- }
- }.start();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- }
- }
这段代码执行下来是可以执行的。但是如果在子线程中执行线程休眠的方法,就会爆出 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.异常。其根本原因在于android实现更新UI的对象。ViewRootImpl是在onResume方法中去初始化的,由于会先执行onCreate方法,所以此时的viewRootImpl还没有被初始化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。