Android更新ui 的几种方式?Handler 机制(二)

  1. activity runonuiThread
    首先判断当前线程是不是UI线程,如果不是UI线程,activity自己有一个handler,通过handler的post 方法来发送一个runnable。如果是UI线程就调用UI 线程的run方法,其实内部还是通过handler机制更新UI
  2. handler post(runnable)
    内部调用sendMessageDelayed()方法 和sendMessage本质上是相同的
  3. handler sendMessage(最常见)
  4. view post
    首先判断AttachInfo是否为空,如果不等于空,则通过AttachInfo拿到handler 。通过AttachInfo.handler.post(runnable)方法来更新UI 。不为空的情况下通过ViewRootImpl.getRunQueue().post(runnable);来更新UI
    总结:这四种方法,本质上还是通过handler机制来更新UI 。只是在内部有些代码上的差异
    代码如下
public class UpdateUIActivity extends Activity {
    private TextView text;
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            text.setText("handler2sendEmptyMessage  UI");       };
    };

    private void handler1() {
        // 第一中方式
        handler.post(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                text.setText("handelr  UI");
            }
        });
    }

    private void handler2() {
        // 第2中方式
        handler.sendEmptyMessage(1);
    }

    private  void updateUI(){
        // 第3中方式
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                text.setText("runOnUiThread  UI");

            }
        });
    }


    private void viewUI(){
        // 第4中方式
        text.post(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                text.setText("viewUIpost  UI");

            }
        });
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_ui);
        text = (TextView) findViewById(R.id.textview1);
        new Thread() {

            @Override
            public void run() {             
                try {
                    Thread.sleep(2000);
                    //handler2();
                    //updateUI();
                    //viewUI();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }.start();
    }

}

非UI线程真的不能更新UI么?
在有些情况下非UI 线程是可以更新UI 的。
可以更新的情况

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_ui);
        text = (TextView) findViewById(R.id.textview1);
        new Thread() {

            @Override
            public void run() {     
                text.setText(" UI");

            }
        }.start();
    }

报错的情况

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_ui);
        text = (TextView) findViewById(R.id.textview1);
        new Thread() {

            @Override
            public void run() {             
                try {
                    Thread.sleep(2000);
                    text.setText(" UI");
                    //handler2();
                    //updateUI();
                    //viewUI();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }.start();
    }

所有更新UI 的操作都会调用view的 invalidate()方法,当我们调用textview.setText()方法会调用checkForRelayout()方法,重新绘制界面,其内部也会调用invalidate()方法。invalidate()方法内部调用ViewParent的invalidateChild()方法,其实真正判断当前线程是否在UI线程中更新界面的操作就是在ViewParent类当中,ViewParent是ViewRootImpl的一个实现类。对于上面的情况,当线程不休眠的时候ViewRootImpl还没有被创建出来,ViewRootImpl在activity的onResume()方法中被创建,onCreate()方法在onResume()方法之前,所以线程不休眠时就没有创建ViewRootImpl,所以就判断是在UI线程更新UI 就可以更新成功。
Avctivity 的启动类是activityThread

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值