學習筆記(三)——關於Service的那些事
Service作為Android四大元件之一,在每一個應用程式中都扮演著非常重要的角色。Service是一個應用元件,能在後臺執行長時間的操作,並且不提供使用者介面;所以Service不是一個單獨的程序也是不是一個執行緒。
專案中的每一個Service都必須在AndroidManifest.xml中註冊才行。
Service生命週期:
從service的生命週期可以看出,從它被建立開始,到它被銷燬為止,可以有兩條不同的路徑:
- startService():必須呼叫stopSelf()方法或者其他元件呼叫stopService()方法來停止它。當service被停止時,系統會銷燬它。
- bindService():客戶端可以通過一個IBinder介面和service進行通訊。可以通過 unbindService()方法來關閉這種連線。一個service可以同時和多個客戶端繫結,當多個客戶端都解除繫結之後,系統會銷燬service。
這兩條路徑並不是完全分開的,我們可以和一個已經呼叫了 startService()而被開啟的service進行繫結。比如一個音樂播放器service可能因呼叫 startService()方法而被開啟了,稍後,可能使用者想要控制播放器或者得到一些當前歌曲的資訊,可以通過bindService()將一個activity和service繫結。這種情況下,stopService()或 stopSelf()實際上並不能停止這個service,除非所有的客戶端都解除繫結。
Service所要重寫的方法:
- onCreate() :建立Service後會被呼叫
- onStartCommand(Intent intent, int flags, int startId)
- onDestroy() :Service關閉之前會呼叫的方法
onBind(Intent intent)
我們通過音樂播放器的例子來更深刻理解這些方法:
public class MusicService extends Service {
private MediaPlayer mediaPlayer;
private IBinder iBinder=new LocalBinder();
@Override
public void onCreate() {
super.onCreate();
mediaPlayer=MediaPlayer.create(this,R.raw.dongting);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return START_NOT_STICKY;//在後臺強制關閉時可以殺死
}
@Override
public void onDestroy() {
mediaPlayer.stop();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
public class LocalBinder extends Binder{
MusicService getService(){
return MusicService.this;
}
} }
上面onBind()方法返回了一個可以得到歌曲的Binder物件,該物件將會傳給訪問該Service的訪問者。
public class MusicActivity extends Activity implements View.OnClickListener{ private Button startbtn; private Button stopbtn; private MusicService musicService; private ServiceConnection serviceConnection=new ServiceConnection(){ @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { //ibender負責service與外界通訊,ibender是從MusicService的onBind()方法中得到的 MusicService.LocalBinder localBinder= (MusicService.LocalBinder) iBinder; musicService = localBinder.getService(); } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.music_button); startbtn = (Button) findViewById(R.id.music_btn_start); stopbtn = (Button) findViewById(R.id.music_btn_stop); startbtn.setOnClickListener(this); stopbtn.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.music_btn_start: startService(new Intent(MusicActivity.this,MusicService.class)); bindService(new Intent(MusicActivity.this,MusicService.class),serviceConnection,BIND_AUTO_CREATE); //要在ManiFest中新增service標籤 break; case R.id.music_btn_stop: unbindService(serviceConnection); stopService(new Intent(MusicActivity.this,MusicService.class)); break; } } }
IntentService:非同步處理服務
Service執行在主執行緒裡,所以它裡面不能處理一個耗時操作,否則會報出異常。
IntentService的特點:
IntentService有以下特點:
(1) 它建立了一個獨立的工作執行緒來處理所有的通過onStartCommand()傳遞給服務的intents。
(2) 建立了一個工作佇列,來逐個傳送intent給onHandleIntent()。
(3) 不需要主動呼叫stopSelft()來結束服務。因為,在所有的intent被處理完後,系統會自動關閉服務。
(4) 預設實現的onBind()返回null
(5) 預設實現的onStartCommand()的目的是將intent插入到工作佇列中