子线程更新UI界面的2种方法

摘要:
使用Handler时,需要实现handleMessage方法来对特定的Message进行处理,例如更新UI等。MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。子线程更新uI界面方法一:用Handler1、我们将在上张AsyncTask的案例中进行操作,我们将之前点击调用事件中的调用方法注释。

一、一般我们都会在子线程完成一些耗时的操作。

1、Android中消息机制:

子线程更新UI界面的2种方法第1张

2、知识点:

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

子线程更新uI界面方法一:用Handler

1、我们将在上张AsyncTask的案例中进行操作,我们将之前点击调用事件中的调用方法注释。

public class MainActivity extendsActivity {
    privateSimpleAdapter sa;
    privateButton btn;
    privateTextView tv;
    private List<Userinfos> list=new ArrayList<Userinfos>();
    privateBaseAdapter adapter;
    privateListView lv;  
    privateRunnable doInBackground1;
    privateRunnable doInBackground2;
    privateRunnable doInBackground3;
    privateHandler handler;
    privateThread th;
    privateThread th2;
    @Override
    protected voidonCreate(Bundle savedInstanceState) {
        //这里是UI主线程 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i < 5; i++) {
            Userinfos u = newUserinfos();
            u.setName("小明"+i);
            u.setSex("男"+i);
            list.add(u);
        }
        lv=(ListView)this.findViewById(R.id.listView1);
        tv=(TextView)findViewById(R.id.textView1);
        btn=(Button)findViewById(R.id.button1);
        btn.setOnClickListener(newOnClickListener(){

              //模拟数据访问产生数据
@Override
            public voidonClick(View v) {
                //TODO Auto-generated method stub
                /*Take tk=new Take(MainActivity.this);//同步任务
                tk.execute(list,adapter);//参数是传给doInBackground*/
               Thread t1=new Thread(doInBackground1);
                t1.start();
                Thread t2=new Thread(doInBackground2);
                t2.start();
                Thread t3=new Thread( doInBackground3);
                t3.start();}});
handler=newHandler()
             {
                 public voidhandleMessage(android.os.Message msg)
                 {
                     int what=msg.what;
                     Log.i("handler","已经收到消息,消息what:"+what+",id:"+Thread.currentThread().getId());
                    
                     if(what==1)
                     {
                         Log.i("handler已接受到消息",""+what);
                         tv.setText("子线程一");
                     }
                     if(what==2)
                     {
                         Log.i("handler已接受到消息",""+what);
                         adapter.notifyDataSetChanged();
                        
                     }
                     if(what==3)
                     {
                         Log.i("handler已接受到消息",""+what);
                         adapter.notifyDataSetChanged();
                         btn.setText("子线程三");
                     }
                 };
             };
             //子线程一
            doInBackground1=new Runnable(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    //1.访问数据库或者互联网,不在UI进程,所以不卡
                 Message msg=new Message();
                    //对消息一个识别号,便于handler能够识别
                   msg.what=1;
                    handler.sendMessage(msg);
                    Log.i("dd","子线程一已发送消息给handler");
                }};
                //子线程二
              doInBackground2=new Runnable(){

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        Message mge=new Message();
                        mge.what=2;
                        handler.sendMessageDelayed(mge,200);
                         for(Userinfos us:list)
                         {
                             us.setName("李丽");
                         }
                        Log.i("dd","子线程二已发送消息给handler");
                    
                    }};
                   //子线程三
                    doInBackground3=new Runnable()
                    {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            try {
                                Thread.sleep(9000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            Message mge=new Message();
                            mge.what=3;
                            handler.sendMessageDelayed(mge,200);
                             for(Userinfos us:list)
                             {
                                 us.setSex("女");
                             }
                            Log.i("dd","子线程三已发送消息给handler");
                            
                        }};

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

2、Handler的handleMessage方法进行消息处理,接收到消息进行UI界面更新。

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

效果图:

子线程更新UI界面的2种方法第2张子线程更新UI界面的2种方法第3张

子线程更新uI界面方法二:用用Activity对象的runOnUiThread方法更新

通过runOnUiThread方法进行UI界面更新

public voidonClick(View v) {
                //TODO Auto-generated method stub
                /*Take tk=new Take(MainActivity.this);//同步任务
                tk.execute(list,adapter);//参数是传给doInBackground*/
                /*Thread t1=new Thread(doInBackground1);
                t1.start();
                Thread t2=new Thread(doInBackground2);
                t2.start();
                Thread t3=new Thread( doInBackground3);
                t3.start();*/th.start();
                th2.start();
            }});
th= newThread()
             {
                 @Override
                public voidrun() {
                     //这儿是耗时操作,完成之后更新UI;  
                    runOnUiThread(newRunnable()
                    {
                          //更新UI  
@Override
                        public voidrun() {
                            //TODO Auto-generated method stub
                            btn.setText("runOnUiThread子线程一");
                        }
                        
                    });
                    super.run();
                }
             };
             th2=newThread()
             {
                 public voidrun() 
                 {
                     runOnUiThread(newRunnable()
                     {
                         @Override
                        public voidrun() {
                             try{
                                Thread.sleep(3000);
                            } catch(InterruptedException e) {
                                //TODO Auto-generated catch block
e.printStackTrace();
                            }
                            //TODO Auto-generated method stub
                            tv.setText("runOnUiThread子线程二");
                        }
                         
                     });

                 };
                 
             };

1、通过runOnUiThread方法New 一个Runnable实现run方法进行UI界面更新。

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

效果图片:

子线程更新UI界面的2种方法第4张

免责声明:文章转载自《子线程更新UI界面的2种方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇复杂SQL代码实例mis系统的技术需求下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Mysql主从同步的实现原理与配置实战

1、什么是mysql主从同步? 当master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库。 2、主从同步有什么好处? 水平扩展数据库的负载能力。 容错,高可用。Failover(失败切换)/High Availability 数据备份。 3、主从同步的原理是什么? 首先我们来了解master-slave的体系结构。如下图:...

Java内存模型(JMM)详解

在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型。它们的答案是一致的:能够让我们更好的理解底层原理,写出更高效的代码。 就Java内存模型而言,它是深入了解Java并发编程的先决条件。对于后续多线程中的线程安全、同步异步处理等更是大有裨益。 硬...

《Linux/UNIX系统编程手册》第43章 进程间通信简介

关键词:pipe、fifo、stream socket、datagram socket、message queue、Share Memory、memory mapping、signal、semaphore。mutex、condition variable等等。 本章是后面章节的简要介绍,包括管道和FIFO;System V和POSIX IPC的消息队列、信...

Java学习-074-多线程07:后台线程 Thread.setDaemon(true)

Java 程序中,只要前台存在一个线程,则 Java 进程(程序)都不会消失。在前台线程存续期间,可以设置一个后台线程,线程设置为后台线程可通过 Thread.setDaemon(true) 实现。示例代码如下所示: packagecom.fanfengping.demo; importlombok.extern.slf4j.Slf4j; /*** J...

【java虚拟机】jvm内存模型

作者:pengjunlee原文链接:https://blog.csdn.net/pengjunlee/article/details/71909239 目录 一、运行时数据区域   1、程序计数器   2、Java 虚拟机栈   3、本地方法栈   4、Java 堆   5、方法区   6、运行时常量池   7、直接内存 二、OutOfMemoryErro...

微信公众平台开发(二):交互与接口

1、微信用户、微信服务器和后台服务器的交互 例:微信用户向公众号发送一条文本消息,这条消息会首先传给微信服务器,微信服务器处理这条信息并将其以xml数据格式传递给后台服务器,后台服务器接受到数据后会对数据进行处理,再响应数据以xml数据格式传递给微信服务器,微信服务器再响应到用户微信界面。 微信用户与微信后台服务器之间的交互过程就是数据传递过程,只不过需...