您的位置:首页 > 产品设计 > UI/UE

Android子线程中更新UI的3种方法

2016-11-11 11:38 459 查看
转载: http://gqdy365.iteye.com/blog/2112471
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 

在看方法之前看一下Android中消息机制: 


 

引用

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。 

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。 

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。 

Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。 

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。 

不熟悉的朋友可以参考一下这篇文档: 
Android知识梳理:消息机制之Handler:http://gqdy365.iteye.com/blog/2148925 Android知识梳理:消息机制之Looper :http://gqdy365.iteye.com/blog/2137494 

下面基于上述原理说一下更新方法: 
方法一:用Handler 

1、主线程中定义Handler: 

Java代码  


Handler mHandler = new Handler() {  

  

        @Override  

        public void handleMessage(Message msg) {  

            super.handleMessage(msg);  

            switch (msg.what) {  

            case 0:  

                //完成主界面更新,拿到数据  

                String data = (String)msg.obj;  

                  

                updateWeather();  

                textView.setText(data);  

                break;  

            default:  

                break;  

            }  

        }  

  

    };  

2、子线程发消息,通知Handler完成UI更新: 

Java代码  


private void updateWeather() {  

          

          

        new Thread(new Runnable(){  

  

            @Override  

            public void run() {  

                //耗时操作,完成之后发送消息给Handler,完成UI更新;  

                mHandler.sendEmptyMessage(0);  

                  

                //需要数据传递,用下面方法;  

                Message msg =new Message();  

                msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等;  

                mHandler.sendMessage(msg);  

            }  

              

        }).start();  

          

    }  

方法一的Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用; 

方法二:用Activity对象的runOnUiThread方法更新 
在子线程中通过runOnUiThread()方法更新UI: 

Java代码  


new Thread() {  

            public void run() {  

                //这儿是耗时操作,完成之后更新UI;  

                runOnUiThread(new Runnable(){  

  

                    @Override  

                    public void run() {  

                        //更新UI  

                        imageView.setImageBitmap(bitmap);  

                    }  

                      

                });  

            }  

        }.start();  

如果在非上下文类中(Activity),可以通过传递上下文实现调用; 

Java代码  


Activity activity = (Activity) imageView.getContext();  

                activity.runOnUiThread(new Runnable() {  

  

                    @Override  

                    public void run() {  

                        imageView.setImageBitmap(bitmap);  

                    }  

                });  

这种方法使用比较灵活,但如果Thread定义在其他地方,需要传递Activity对象; 

方法三:View.post(Runnable r) 

Java代码  


imageView.post(new Runnable(){  

  

                    @Override  

                    public void run() {  

                        imageView.setImageBitmap(bitmap);  

                    }  

                      

                });  

这种方法更简单,但需要传递要更新的View过去; 
总结:UI的更新必须在主线程中完成,所以不管上述那种方法,都是将更新UI的消息发送到了主线程的消息对象,让主线程做处理;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: