首页 > 代码库 > 子线程更新UI界面的2种方法

子线程更新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),可以通过传递上下文实现调用; 

效果图片:

           技术分享

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