zoukankan      html  css  js  c++  java
  • Android开发——子线程操作UI的几种方法

    Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:

    在看方法之前需要了解一下Android中的消息机制

    转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52120389


    方法1  Activity.runOnUiThread

    方法如下:

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
          tv.setText("Hello");
        }
    });
    这种方法简单易用,如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,发布到事件队列的UI线程。其实和Handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。


    方法2  Handler

    主线程中定义Handler如下:

    Handler mHandler = new Handler() {  
            @Override  
            public void handleMessage(Message msg) {  
                super.handleMessage(msg);  
                switch (msg.what) {  
                case 0:  
                    String data = (String)msg.obj;  
                    textView.setText(data);  
                    break;  
                default:  
                    break;  
                }  
            }  
        };
    

    子线程发消息,通知Handler完成UI更新,代码如下:

    new Thread(new Runnable(){  
                @Override  
                public void run() {  
                    //耗时操作                
                    mHandler.sendEmptyMessage(0);  
                    Message msg =new Message();  
                    msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等 
                    mHandler.sendMessage(msg);  
                }  
            }).start();  
    

    方法3  View.post

    final Button btn =(Button)findViewById(R.id.btn);
    btn.post(new Runnable(){
    @Override
        publicvoid run() {
        btn.setText("Hello");
        }
      }); 

    上面的代码就是更新btn中的内容,同样下面的代码也可以达到这种效果。

    Handler handler = new Handler();
    final Button btn = (Button)findViewById(R.id.btn);
    handler.post(new Runnable(){
        @Override
        public void run() {
        btn.setText("Hello");
      }
    }); 

    这个是用handler.post方法,一个是用View.post方法,handler.post方法已经在Android的消息机制中介绍过了,其实最终也是调用了方法2中的send方法。

    现在看一下View.post方法的源代码:

    public boolean post(Runnable action) {
    Handler handler;
    AttachInfo attachInfo = mAttachInfo;
    if (attachInfo != null) {
        handler = attachInfo.mHandler;
    } else {
        // Assume that post will succeed later
        ViewRootImpl.getRunQueue().post(action);
        return true;
    }
        return handler.post(action);
    }

    方法中主要的功能代码就是attachInfo.mHandler,获取当前线程(即UI线程)的Hanlder然后将action对象postHandler里。在Handler里的处理过程上面链接文已经分析的很清楚了,它将传递过来的action对象包装成一个MessageMessagecallbackaction),然后将其投入UI线程的消息循环中。在HandlerdispatchMessage方法里,第一句话就是为它所设,直接调用runnablerun方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI


    方法广播

    子线程中发送广播,主线程中接收广播并更新UI


    方法5  使用AsyncTask

    为了简化子线程中访问UI,系统提供给了我们AsyncTask

    AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行进度和结果传递给主线程并更新UI。本质上来说AsyncTask封装了ThreadHandler,但是AsyncTask不适合进行特别耗时的后台任务,如果需要进行特别耗时的任务,建议使用线程池。

    不同API版本的AsyncTask具有不同的表现,因此需要注意。为了控制篇幅,具体的AsyncTask的使用方法和工作原理,写在这篇文章,AsyncTask的使用以及源码解析,有兴趣的同学可以查看。

  • 相关阅读:
    Java 9 揭秘(14. HTTP/2 Client API)
    Java 9 揭秘(13. Collection API 更新)
    Java 9 揭秘(12. Process API 更新)
    JAVA数组与List相互转换
    linux下开启oracle服务和开启监听
    Centos7安装Redis
    Hibernate乐观锁无法Catch到org.hibernate.StaleObjectStateException
    Eclipse远程调试Tomcat
    Centos7 使用Docker搭建Oracle测试环境
    Maven安装Oracle驱动包到本地仓库
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461578.html
Copyright © 2011-2022 走看看