1. 程式人生 > >學習筆記(三)——關於Service的那些事

學習筆記(三)——關於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插入到工作佇列中