android子线程更新UI

参考:https://www.cnblogs.com/joy99/p/6121280.html

子线程是不能直接更新UI的。Android实现View更新有两组方法,分别是invalidatepostInvalidate。前者在UI线程中使用,后者在非UI线程即子线程中使用。换句话说,在子线程调用 invalidate 方法会导致线程不安全。熟悉View工作原理的人都知道,invalidate 方法会通知 view 立即重绘,刷新界面。作一个假设,现在我用 invalidate 在子线程中刷新界面,同时UI线程也在用 invalidate 刷新界面,这样会不会导致界面的刷新不能同步?这就是invalidate不能在子线程中使用的原因。

  但是我们可以在子线程执行某段代码,需要更新UI的时候去通知主线程,让主线程来更新。如何做呢?常见的方法,除了前面提到的在UI线程创建Handler,在子线程发送消息到UI线程,通知UI线程更新UI,还有 handler.post(Runnable r)、 view.post(Runnable r)、activity.runOnUIThread(Runnable r)等方法。跟进去看源码,发现其实它们的实现原理都还是一样,最终都是通过Handler发送消息来实现的。下面分别用这几种方法实现一下在子线程更新UI。

public class MainActivity extends Activity implements View.OnClickListener{

    Button bt1;
    Button bt2;
    Button bt3;
    Button bt4;
    Button bt5;
    TextView tv;

    Handler mhandler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==100){
                tv.setText("Handler更新的");
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = findViewById(R.id.tv);

        bt1 = findViewById(R.id.bt1);
        bt2 = findViewById(R.id.bt2);
        bt3 = findViewById(R.id.bt3);
        bt4 = findViewById(R.id.bt4);
        bt5 = findViewById(R.id.bt5);

        bt1.setOnClickListener(this);
        bt2.setOnClickListener(this);
        bt3.setOnClickListener(this);
        bt4.setOnClickListener(this);
        bt5.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt1:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText("子线程更新UI:报错!!!");
                    }
                }).start();
                break;
            case R.id.bt2:
                mhandler.sendEmptyMessage(100);
                break;
            case R.id.bt3:
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText("Handler post更新UI");
                    }
                });
                break;
            case R.id.bt4:
                tv.post(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText("View post更新UI");
                    }
                });
                break;
            case R.id.bt5:
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText("Activity runOnUiThread更新UI");
                    }
                });
                break;
        }
    }
}

原文地址:https://www.cnblogs.com/maogefff/p/8317063.html