安卓開發四大組件之一——Service,可以理解為幕后工作者,音樂詞曲作家,哈哈。那么在開發中,音樂播放,下載文件,上載文件都用到service。Service,分為本地服務和遠程服務,區分是客戶端和服務端是否在同一進程當中,在為本地服務,不在為遠程服務,下面著重介紹本地服務,是安卓開發中最常用到的。啟動服務有兩種方式,startService和bindService;結束服務有兩種方式,startService對應stopService或stopSelf,bindService對應unBindService;startService和bindService;——兩者之間的區別:startService啟動服務后,客戶端和服務端再就沒有聯系了,也就是之間沒有通信,要結束服務,要不在啟動服務的地方調用stopService或者在服務中調用stopSelf;bindService啟動服務后,服務和客戶端是有交互的,他們之間是通過binder對象進行交互的,要結束服務,在客戶端調用unBindService,bindService在開發中是最常用的,所以著重要講解。
切記在使用service時,一定要在AndroidManifest.xml中進行配置,如何配置,Activity怎么配置,服務就怎么配置。例如項目中下載視頻服務的配置
<!-- 下載視頻服務器 --> <service android:name="com.suowei.appsuowei.service.UpVideoService"/>1、startService:
生命周期:
onCreate ---> onStart ---> onDestory(Android 2.0以下版本中使用)
onCreate ---> onStartCommand ---> onDestory(Android2.0以上版本中使用)
當第一次調用startService后,先調用onCreate,再調用onStart或者onStartCommand,結束服務,調用onDestory,這里要特別注意的,如果已經啟動了該服務,如果再次調用startService,那么不會調用onCreate,直接調用onStart或onStartCommand。
特別注意的是:onStartCommand方法返回一個int值,這個值有四種:
(1)START_STICKY:如果service進程被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent對象。隨后系統會嘗試重新創建service,由于服務狀態為開始狀態,所以創建服務后一定會調用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那么參數Intent將為null。(2)START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完onStartCommand后,服務被異常kill掉,系統將會把它置為started狀態,系統不會自動重啟該服務,直到startService(Intent intent)方法再次被調用;。(3)START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,如果在執行完onStartCommand后,服務被異常kill掉,系統會自動重啟該服務,并將Intent的值傳入。(4)START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務被kill后一定能重啟。2、bindService:生命周期:bindService時:onCreate ---> onBindunBindService時:onUnBind ---> onDestory現在分步講解:在調用bindServcie時,要傳入三個參數this.bindService(intent, conn, Context.BIND_AUTO_CREATE); 第一個參數intent為意圖,用的滾瓜爛熟了吧Intent intent=new Intent(this,UpVideoService.class);第二個參數conn為實現了服務鏈接接口(ServiceConnection)的類的對象PRivate class UpVideoConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { } @Override public void onServiceDisconnected(ComponentName name) {} }第一個方法在啟動服務后鏈接上服務調用,第二個為斷開服務鏈接時調用,大家注意,在第一個方法中傳入了一個Ibinder接口變量,這個變量就是客戶端與服務進行通信的橋梁紐帶,客戶端與服務端要通信,必須要拿到Service對象,才能調用Service中的公共方法,在android中的Service使用onBind的方法綁定服務時,返回一個實現IBinder接口的對象,所以在Service對象內部有一個Binder對象并返回,在這個對象中,寫一個方法得到該Service,這樣在上面的onServiceConnected中返回一個binder對象,用這個對象拿到Service對象,這樣就可以隨意調用Servcie中的公共方法了,實現了客戶端有服務器端的通信@Override public IBinder onBind(Intent intent) { return new VideoBinder; }上面這個方法是用來返回Binder對象的那么現在在服務里面寫一個類(在這個類中寫一個公共方法,getService,返回值為該服務)public class VideoBinder extends Binder{ public UpVideoService getService(){ return UpVideoService.this; } }那么現在就把這個類的對象進行返回,把null改為VideoBinder對象,public IBinder onBind(Intent intent) { return new VideoBinder();}那么這樣,在客戶端返回的Binder對象,調用自己的方法,就獲取到了Service,接下來想怎么操作Service中的方法就看你的需要了。3、IntentService這家伙也得講解下,不然學員又混淆了,首先IntentService是Service的子類,那么他就擁有Service所有的屬性,既然是子類,那肯定有自己獨特的好用之處了。在講解這個IntentService之前,學員必須搞清一個問題,Service與Activity運行在不在同一個線程當中,答案是默認情況下他們都在進程的主線程中,哈哈,為了防止服務訪問耗時操作或者線程阻塞,導致ANR,必須要新開線程,那么不得不在Service中編寫耗時操作或者邏輯時,引入了IntentService,在intentService中,已經為你新開了一個線程,所以程序員在不必要新開線程了,而在IntentService中,只提供了一個方法protected abstract void onHandleIntent(Intent intent);這是一個抽象方法,要實現必須要重寫了,通過查閱源代碼,IntentService是通過Handler looper message的方式實現了一個多線程的操作,同時耗時操作也可以被這個線程管理和執行,同時不會產生ANR的情況。說來說去,大家記住嘍,一代比一代永遠強。附上IntentService源碼,有興趣的可以看看,剛學習的不建議看,到此為止private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public IntentService(String name) { super(); mName = name; } /** * Sets intent redelivery preferences. Usually called from the constructor * with your preferred semantics. * * <p>If enabled is true, * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT}, so if this process dies before * {@link #onHandleIntent(Intent)} returns, the process will be restarted * and the intent redelivered. If multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. * * <p>If enabled is false (the default), * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent * dies along with it. */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
新聞熱點
疑難解答