Android Demo之旅 Activity、Service、BroadCast實現計數統計
時間匆匆,轉眼就是大半個月過去了,學習android的道理上艱苦而漫長呀!!自己寫了很多的小demo,總結總結,也在部落格裡面留點足跡吧!
原始碼下載:http://download.csdn.net/detail/harderxin/7761401 參考執行個體:老羅部落格
實現功能:統計計數,我們可能有很多種方式來實現它,但是這個執行個體運用了Activity、Service、BroadcastReceiver在android中三個大知識點,所以覺得它比較有參考價值;
可學知識點:1)Activity、Service的生命週期;2)bindService的用法;3)代碼註冊BroadcastReceiver;4)學習使用非同步載入類AsyncTask
功能邏輯:參考下面流程圖:
啟動Activity後,在相應的Activity生命週期中綁定Service和註冊廣播接收者,當使用者點擊按鈕時,啟動AsyncTask非同步處理邏輯,也就是加數,然後將結果時時發送到廣播中,廣播接收者接到廣播後時時更新Activity;
實現功能:
功能詳解:因為有原始碼,所以我只講解該小應用的核心代碼:
1)啟動Activity,綁定Service
//通過bindService方法會將計數器服務CounterService啟動起來 //serviceConn為ServiceConnection的一個執行個體,伺服器啟動起來後 //系統會調用ServiceConnection裡面的onServiceConnected方法將Service中 //的CounterBinder對象傳回來,得到相應的Service //當我們調用unBindService停止服務時,會調用其onServiceDisconnected方法 Intent bindIntent=new Intent(MainActivity.this,CounterService.class); bindService(bindIntent, serviceConn, Context.BIND_AUTO_CREATE);
//建立Service連線物件 private ServiceConnection serviceConn=new ServiceConnection() { @Overridepublic void onServiceDisconnected(ComponentName name) {counterService=null;Log.i(TAG, "Counter Service Disconnected");}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {counterService=((CounterService.CounterBinder)service).getService();Log.i(TAG, "Counter Service Connected");}};
在Service中建立與Activity打交道的Binder對象:
//Activity和Service的關聯紐帶public class CounterBinder extends Binder{public CounterService getService(){return CounterService.this;}}private final IBinder binder=new CounterBinder();//當系統調用bindService時候,該方法會被執行,返回一個自訂的Binder對象給系統@Overridepublic IBinder onBind(Intent arg0) {Log.i(TAG,"Counter Service onBind");return binder;}
2)註冊廣播接收者
//建立一個廣播對象,接收從CounterService中發送過來的廣播資訊,並將相應的資訊顯示在介面上private BroadcastReceiver counterActionReceiver=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {int counter=intent.getIntExtra(CounterService.COUNTER_VALUE, 0);count=counter;counterText.setText(count+"");Log.i(TAG, "Receive counter event");}};@Overrideprotected void onResume() {super.onResume();Log.i(TAG, "MainActivity onResume");//註冊一個廣播接收器,該廣播接收器指定了只對CounterService.BROADCAST_COUNTER_ACTION//類型的廣播感興趣,當CounterService發送一個廣播後sendBroadcast,該廣播就會被counterActionReceiver//中的onReceive函數接收處理//這裡是通過代碼的形式註冊我們的廣播,我們也可以在xml中進行相應的註冊IntentFilter counterActionFilter=new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);registerReceiver(counterActionReceiver, counterActionFilter);}
3)點擊計數按鈕,非同步處理邏輯,並時時發送廣播:
public void startCounter(int initVal) {//使用非同步進行後台計數//為什麼使用它?因為這個計數的過程我們可以將其類比一個耗時的計算邏輯,耗時的操作則不能在主線程中進行//否則會出現ANR(Application not responding)現象//也可以使用Handler與線程的結合進行AsyncTask task=new AsyncTask() {@Overrideprotected Integer doInBackground(Integer... params) {Log.i(TAG, "doInBackground execute");Integer initCounter=params[0];stop=false;while(!stop){//調用該方法系統會自動調用onProgressUpdate方法publishProgress(initCounter);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}initCounter++;}return initCounter;}@Overrideprotected void onProgressUpdate(Integer... values) {Log.i(TAG, "onProgressUpdate execute");super.onProgressUpdate(values);int counter=values[0];//將時時更新的值廣播出去Intent intent=new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}@Overrideprotected void onPostExecute(Integer result) {Log.i(TAG, "onPostExecute execute");int counter=result;//將時時更新的值廣播出去Intent intent=new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}};task.execute(initVal);}
4)廣播接收者接收廣播,並時時更新介面:
@Overridepublic void onReceive(Context context, Intent intent) {int counter=intent.getIntExtra(CounterService.COUNTER_VALUE, 0);count=counter;counterText.setText(count+"");Log.i(TAG, "Receive counter event");}
因為AsyncTask的執行個體化和啟動必須在UI線程中,也就是說在主線程中,該程式中,Activity和Service同在主線程中,所以我們能夠在Service中執行個體化和啟動AsyncTask!