Android---元件篇---Handler的使用(1)[轉]

M'發表於2013-07-11

在android中,有很多功能是不能放在onCreate或者onStart方法裡面,因為這些功能相對

來說費時比較長,比如說下載一個檔案,下載的過程比較長,但是如果寫在Activity中,

那麼這段時間Activity是完全沒有響應的,那麼就可以將這種處理大量資料或者耗時比較

長的東西放在一個單獨的執行緒中來完成,即Activity是一個執行緒,而下載的是在另外一個

執行緒,那麼這樣就可以使得下載跟Activity之間互不影響,從而得到了良好的使用者體驗

 

這裡有兩種佇列,一種是執行緒佇列,就是用postXX方法或者removeCallbacks方法對執行緒物件的操作。另一種是訊息佇列,用sendMessage和handleMessage方法來對訊息物件進行處理

handler採用的是一個訊息佇列的方式,每一個handler都有一個與之關聯的訊息佇列,而且是先進先出的方式執行,即:每次加入一個handler,然後拿出來,對其進行處理,然後再拿出另一個,再進行處理

 

例子一:這個例子僅僅是對執行緒物件進行操作的測試

package org.hualang.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;

public class HandlerTest extends Activity {
    
    private Button mybutton1;
    private Button mybutton2;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mybutton1 = (Button)findViewById(R.id.mybutton1);
        mybutton2 = (Button)findViewById(R.id.mybutton2);
        
        mybutton1.setOnClickListener(new Button.OnClickListener()
        {

            @Override
            public void onClick(View arg0) {
                /**
                 * 呼叫Handler的post方法,將要執行的執行緒物件新增到
                 * 執行緒佇列中
                 */
                handler.post(updateThread);
            }
            
        });
        mybutton2.setOnClickListener(new Button.OnClickListener()
        {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                handler.removeCallbacks(updateThread);
            }
            
        });  
        
    }
    //建立Handler物件
    Handler handler = new Handler();
    /**
     * 將要執行的操作解除安裝寫入執行緒物件的run()方法當中
     */
    Runnable updateThread = new Runnable()
    {
        public void run()
        {
            System.out.println("更新執行緒");
            //在run方法內部,執行postXX的方法,每隔3秒會執行一次
            handler.postDelayed(updateThread, 3000);
        }
    };
}

程式解釋:首先建立一個Handler物件,然後建立一個繼承自Runnable介面的執行緒

程式首先點選按鈕“開始”,於是會馬上執行post方法,將執行的執行緒物件新增到執行緒佇列中,這時會馬上執行

public void run()
        {
            System.out.println("更新執行緒");
            //在run方法內部,執行postXX的方法,每隔3秒會執行一次
            handler.postDelayed(updateThread, 3000);
        }

然後,執行postDelayed方法,由於裡面設定的間隔時間,所以每3秒會調價一個handler物件到執行緒佇列中,並且一直執行,直到點選“結束”按鈕,呼叫removeCallbacks方法將其從執行緒佇列中移除

 

 

例子2:下面的例子將簡單的對執行緒物件和訊息物件進行處理

package org.hualang.handlertest2;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class HandlerTest2 extends Activity {
    private ProgressBar bar = null;
    private Button start = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bar = (ProgressBar)findViewById(R.id.progress1);
        start = (Button)findViewById(R.id.start);
        start.setOnClickListener(new Button.OnClickListener()
        {

            @Override
            public void onClick(View v) {
                bar.setVisibility(View.VISIBLE);
                handler.post(handlerThread);
            }
            
        });
    }
    /**
     * 使用匿名內部類來複寫hanlder當中的hanldrMessage方法
     * 這裡的msg物件就是從執行緒部分傳送過來的物件
     */
    Handler handler = new Handler()
    {
        public void handleMessage(Message msg)
        {
            bar.setProgress(msg.arg1);
            handler.post(handlerThread);
        }
    };
    //執行緒類,該類使用的是匿名內部類的方式進行宣告
    Runnable handlerThread = new Runnable()
    {
        int i = 0;
        public void run()
        {
            System.out.println("開始執行緒");
            i = i + 10;
            /**
             * 得到一個訊息物件,Message類是由android作業系統提供
             * obtainMessage方法用來得到Message物件
             */
            Message msg = handler.obtainMessage();
            /**
             * Message中有個成員變數,即msg獨享的arg1引數
             * 將其值設定為i。用arg1或arg2這兩個成員變數傳遞
             * 訊息,優點是系統效能消耗較少
             */
            msg.arg1 = i;
            try {
                //當前執行緒休眠1秒
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            /**
             * 傳送一個訊息,用sendMessage是將msg加入到訊息
             * 佇列中。而post是將執行緒加入到執行緒佇列中
             */
            handler.sendMessage(msg);
            if( i == 100)
            {
                /**
                 * 如果i=100的時候,就將執行緒物件
                 * 從handler當中移除
                 */
                handler.removeCallbacks(handlerThread);
                bar.setVisibility(View.GONE);
            }
        }
    };
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<ProgressBar
    android:id="@+id/progress1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:visibility="gone"
    style="?android:attr/progressBarStyleHorizontal"
/>
<Button
    android:id="@+id/start"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="點選我"
/>
</LinearLayout>

程式說明:

1、當點選按鈕後,會執行按鈕的onClick方法中的

bar.setVisibility(View.VISIBLE);
handler.post(handlerThread);

將進度條顯示出來,並且將執行緒物件加入到執行緒佇列中

2、執行緒物件對先列印出一個“開始執行緒”,然後i的值增加10,然後從系統中獲取一個Message物件

3、將i賦給Message物件的引數arg1

4、當前執行緒休眠5秒,然後通過sendMessage方法傳送一個Message物件傳送到訊息佇列中

5、然後再執行,通過handleMessage方法設定進度條的值,並且將其加入到程式佇列中

Handler handler = new Handler()
    {
        public void handleMessage(Message msg)
        {
            bar.setProgress(msg.arg1);
            handler.post(handlerThread);
        }
    };

6、迴圈執行,直到i=100,進度條隱藏,並將執行緒物件從執行緒佇列中取出

 

 

原文:http://www.iteye.com/topic/1062942

 

 

相關文章