首先來看一下啓動服務的兩種方式startService和bindService:ide
StartService(Intent intent)spa
start的方式只能簡單的開啓服務,而且開啓以後基本不能勇於服務的運行邏輯,話句話說,開啓後服務就和開啓服務的線程沒什麼關係了。可是一般咱們都是更加緊密的去聯繫服務,可能會獲取一些運行的結果,好比執行結果,進度信息等,那就須要使用bind的方式開啓服務了線程
bindService地方法就比較豐富,其傳入三處有三個,類型分別爲代理
Intent,ServiceConnection,Int. 其中第一個就不細說了,意圖你們都明白,第二個爲接口,其中包含兩個必須實現的方法: onServiceConnected(ComponentName var1, IBinder var2) 表明服務鏈接,第一個參數暫且不提,第二個先記住它叫Ibindr,後面會提到。 onServiceDisconnected(ComponentName var1) 表明與服務失去鏈接 第三個參數Int類型就是服務執行的模式。
雖然BindService參數豐富,功能強大,可是其使用邏輯也略微複雜,下面慢慢道來。code
採用bind的方法綁定開啓服務component
a>先new一個類實現ServiceConnection接口,這個類用於爲bind方法的第二個是參數作準備,我理解是定義與服務的鏈接通道。對象
private class MyConn implements ServiceConnection{ //通道成功鏈接 @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { //此處IService表明在Service中提供一個調用其內部方法的接口,爲接口類型 mybinder= (IService) iBinder; Log.d("phone.....","3. 見到服務的代理對象:"+mybinder.toString()); } //通道失去鏈接 @Override public void onServiceDisconnected(ComponentName componentName) { } }
b>實例化出通道,而後使用執行bind方法。blog
在外部類: private MyConn comm; 內部方法: comm=new MyConn(); bindService(intent,comm, Context.BIND_AUTO_CREATE); 其中Context.BIND_AUTO_CREATE表明若服務不存在實例則建立實例
服務內部實現一個代理人類,這個代理繼承自Ibinder,也就是上文ServiceConnection中的onServiceConnected方法的一個返回值,這個Ibinder對象就是服務中的代理在阜外外部的一個引用,經過這個引用就能夠調用Ibinder實現的接口中的方法。繼承
private class Mybinder extends Binder implements IService{ //由代理去調用服務內部的方法 public void callinService(){ Log.d("phone.....","5. 代理人執行了服務裏的方法"); @Override callInService(); } }
定義IService的接口接口
這個接口就是上文提到的IService接口,這個接口中一般定義想要暴露給外部的方法,外部也只能看到IBinder中實現的這個接口的方法,除非你將上一節中的MyBinder這個類定義爲Public。
public interface IService { public void callInService(); }
返回代理人對象
具體服務是如何將IBinder的引用返回給外部呢,就是經過Service惟一的必須實現的方法:
@Nullable @Override public IBinder onBind(Intent intent) { //當有需求時,呼叫代理人去接待 Mybinder mybinder=new Mybinder(); Log.d("phone.....","2. 成功綁定,返回服務的代理對象:"+mybinder.toString()); return mybinder; }
實現serviceConnection接口裏面的方法
如今你就能夠在通道中看到Service的代理對象了:
private class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (IService) service; System.out.println("Activity,獲得代理人對象"); }
調用接口裏面的方法
經過MyBinder這個Service的代理對象,就能夠執行服務中對外開放的方法了。固然這個方法就須要你本身去定義了。
mybinder.callInService();
最後的最後,大體說明一下兩種方式開啓服務的特色
生命週期
oncreate()--->onstartcommand()--->onstart()--->onDestroy()
能夠屢次調用,不會重複建立,oncreate()只會執行一次
以start方式開啓的服務也只能中止一次,屢次調用stopservice()是無效的
以start方式開啓的服務與UI線程失去關係,即便UI線程被銷燬,服務仍然能夠正常運行
不能調用服務中的方法
生命週期
oncreate() --->onbind() -->onunbind()---->ondestry();
只能成功綁定和解綁一次
與綁定的UI線程同時被銷燬(一根繩上的螞蚱^_^)
能夠調用服務中的方法
既然start開啓的服務不能調用方法,bind方式開啓的服務生命力又很弱,那麼可否兩種方式的有點麼?答案固然是確定的,不然服務的應用能力就太弱了。
經過startService()方式開啓服務(只能經過調用stopService中止)
經過bindService進行綁定,以進行服務的方法調用(當須要的時候)
經過unbindService進行解綁(不須要調用方法了,在UI線程被銷燬以前解綁)
經過stopService中止服務
這樣咱們就能夠靈活的使用Service,當須要的時候能夠隨時進行調用,不要的時候又能夠長期運行於後臺而不用保留UI線程。這也是服務最多見的用法。