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

  • 相关阅读:
    【阿里前端面试点】目标,想成为一名好的前端工程师
    JavaScript实现数据双向绑定的三种方式
    a标签的下载链接,如果是图片,点击链接是下载一个图片而不是直接打开,应该怎么办?(添加download属性)
    AngularJs scope详解
    setTimeout可以传第三个甚至更多个参数
    (转) css3中的border-radius详解
    (转) JS原生对象、内置对象、宿主对象的区别
    纯css写的步骤条
    css如何实现滚动条隐藏但鼠标仍然可以滚动
    Js 与浮点数
  • 原文地址:https://www.cnblogs.com/maogefff/p/8317063.html
Copyright © 2020-2023  润新知