IntentService類 和 異步任務(AsyncTask)

IntentService是一個Service類。
IntentService只有1個帶String參數的構造方法,因此,在自定義類繼承IntentService時,須要在自定義類中顯式的調用IntentService帶參數的構造方法,而且將自定義類的構造方法修改成無參數的。
IntentService內部使用消息機制,利用消息隊列的特性,能夠依次處理多個耗時操做。
IntentService具備生命力強、一次性使用、依次處理多個耗時操做的特性。
注意:在自定義類繼承IntentService時,能夠重寫IntentService的生命週期方法,可是,不能夠刪除super語句java


IntentService與ResultReceiver
----------------------------------
ResultReceiver能夠實現組件間的通訊
【開發流程】
1. 自定義類繼承IntentService,顯式的定義無參數的構造方法,並註冊
2. 在接收結果的類(例如Activity類)中自定義內部類繼承ResultReceiver
3. 在須要IntentService執行任務時,使用startService()激活Service組件,而且,將自定義的ResultReceiver對象封裝到用於激活IntentService的Intent對象中
4. 在IntentService的onStartCommand()方法中,經過參數Intent獲取ResultReceiver對象
5. 在IntentService的onHandleIntent()方法中,在須要向Activity提交數據時,調用ResultReceiver的send()方法,發送數據
6. 在自定義的ResultReceiver類中,重寫onReceiveResult()方法獲取IntentService發送過來的數據,並進行處理
【注意事項】
1. IntentService中,重寫生命週期方法必須確保super.xxxx()是存在,即保留調用父類的對應的方法
2. IntentService必須有無參數的構造方法
3. IntentService應該是使用startService激活的
4. 當使用自定義的ResultReceiver時,在IntentService中,必須將對象聲明爲ResultReceiver,而不能夠是自定義的數據類型異步


public class WorkService extends IntentService {
    private ResultReceiver rr;

    public WorkService() {
        super("");
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        rr = intent.getParcelableExtra("receiver");
        return super.onStartCommand(intent, flags, startId);
    }
    
    public static final int CODE_UPDATE_PROGRESS = 1;
    public static final String KEY_PROGRESS = "progress";

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle resultData = new Bundle();
        for (int i = 1; i <= 100; i++) {
            Log.d("tag", "Thread id=" + Thread.currentThread().getId() + ", i=" + i);
            
            resultData.putInt(KEY_PROGRESS, i);
            rr.send(CODE_UPDATE_PROGRESS, resultData);
            
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

public class MainActivity extends Activity implements View.OnClickListener {
    private Button btnStart;
    private ProgressBar progressBar;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        btnStart = (Button) findViewById(R.id.button1);
        progressBar = (ProgressBar) findViewById(R.id.progressBar1);
        
        btnStart.setOnClickListener(this);
        
        handler = new Handler();
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent(this, WorkService.class);
        ResultReceiver rr = new InnerResultReceiver(handler);
        intent.putExtra("receiver", rr);
        startService(intent);
    }
    
    private class InnerResultReceiver extends ResultReceiver {

        public InnerResultReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            if(resultCode == WorkService.CODE_UPDATE_PROGRESS) {
                int progress = resultData.getInt(WorkService.KEY_PROGRESS);
                progressBar.setProgress(progress);
            }
        }
        
    }

}


異步任務(AsyncTask)
----------------------------------
AsyncTask是抽象類,須要自定義類繼承並現實。
AsyncTask是集成了後臺執行任務、更新進度、處理結果的一個工具,開發者在使用時無須關注子線程與主線程通訊的問題。
當存在多個AsyncTask時,多個任務會依次執行。】
【AsyncTask中的泛型】
當繼承自AsycnTask時,須要指定3個數據類型:
1. Prarams:參數的類型,即執行任務時須要提供的參數的數據類型,在實際執行,該參考表現爲可變/變長參數
2. Progress:進度的類型,即執行任務期間是否須要提交進度,若是須要,則表現爲表示進度的數據類型,例如Integer、Float等
3. Result:結果的類型,即執行任務完成後是否須要處理結果,若是須要,則表現爲結果的數據類型,例如加載/下載圖片時能夠使用Bitmap表示該類型
【AsyncTask中的方法】
1. doInBackground():執行任務的方法,應該將具體執行的任務的相關代碼編寫在這個方法中,該方法默認是運行在子線程的,因此,不須要另行建立線程
2. publishProgress()與onProgressUpdate():在doInBackground中能夠經過調用 publishProgress()提交進度,而後,重寫onProgressUpdate()方法對進度的更新進行處 理,onProgressUpdate()默認是運行在主線程的,因此能夠直接處理與UI相關的操做
3. onPostExecute():處理任務的結果,與onProgressUpdate()相同,該方法是運行在主線程的。
【注意】
因爲AsyncTask是依次執行的,在須要多個任務同時開始執行,且互相不彼此影響時,最多隻能有1個任務是經過AsyncTask實現的,其它都應該使用線程、消息機制來實現。





        // 判斷Picture對象中是否存在Bitmap數據
        // 若是存在
        //     直接將Bitmap顯示在ImageView
        // 若是不存在
        //     開啓異步任務加載圖片的Bitmap並顯示在ImageView
        if(pic.getBitmap() != null) {
            holder.image.setImageBitmap(pic.getBitmap());
        } else {
            // 開啓異步任務加載圖片的Bitmap並顯示在ImageView
            // 關於異步任務
            // 1. 在子線程中加載圖片,獲得圖片的Bitmap(須要圖片路徑)
            // 2. 不須要更新進度
            // 3. 在主線程中顯示圖片(須要Bitmap,表現爲子線程任務的返回值,還須要ImageView)
            // 小結:在執行任務以前,須要提供圖片路徑、顯示圖片的ImageView這2個參數,能夠使用自定義的任務類的構造方法傳遞
            // 關於異步任務的泛型:
            // 1. 參數類型:Void
            // 2. 進度類型:Void
            // 3. 結果類型:Bitmap
        }ide

    @Override
    public void onClick(View v) {
        new UpdateProgressTask().execute();
    }

    private class UpdateProgressTask extends AsyncTask<String, Integer, Bitmap> {

        @Override
        protected Bitmap doInBackground(String... params) {
            for (int i = 1; i <= 100; i++) {
                Log.d("tag", "Thread id=" + Thread.currentThread().getId() + ", i=" + i);
                
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

    }
相關文章
相關標籤/搜索