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


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

    1、Android中消息机制:

                       

     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 extends Activity {
        private SimpleAdapter sa;
        private Button btn;
        private TextView tv;
        private List<Userinfos> list=new ArrayList<Userinfos>();
        private BaseAdapter adapter;
        private ListView lv;  
        private Runnable doInBackground1;
        private Runnable doInBackground2;
        private Runnable doInBackground3;
        private Handler handler;
        private Thread th;
        private Thread th2;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            //这里是UI主线程 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            for (int i = 0; i < 5; i++) {
                Userinfos u = new Userinfos();
                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(new OnClickListener(){
    
                  //模拟数据访问产生数据
                @Override
                public void onClick(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=new Handler()
                 {
                     public void handleMessage(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界面方法二:用用Activity对象的runOnUiThread方法更新 

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

    public void onClick(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= new Thread()
                 {
                     @Override
                    public void run() {
                         //这儿是耗时操作,完成之后更新UI;  
                        runOnUiThread(new Runnable()
                        {
                              //更新UI  
                            @Override
                            public void run() {
                                // TODO Auto-generated method stub
                                btn.setText("runOnUiThread子线程一");
                            }
                            
                        });
                        super.run();
                    }
                 };
                 th2=new Thread()
                 {
                     public void run() 
                     {
                         runOnUiThread(new Runnable()
                         {
                             @Override
                            public void run() {
                                 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),可以通过传递上下文实现调用; 

    效果图片:

               

  • 相关阅读:
    Windows 编程入门,了解什么是UWP应用。
    java getway springcloud 记录请求数据
    nginx服务器配置传递给下一层的信息的一些参数-设置哪些跨域的域名可访问
    e.printStackTrace() 原理的分析
    关于性能测试组出现的问题查询和优化
    springboot connecting to :mongodb://127.0..0.1:27017/test authentication failed
    redis 集群 slots are covered by nodes.
    @PostConstruct +getapplicationcontext.getbean springboot获取getBean
    idea 错误: 找不到或无法加载主类 xx.xxx.Application
    elastic-job和spring cloud版本冲突2
  • 原文地址:https://www.cnblogs.com/wdht/p/6137584.html
Copyright © 2020-2023  润新知