子線程更新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),可以通過傳遞上下文實現調用; 

效果圖片:

           


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM