BindService() 綁定方式開啓服務

Bind方式開啓服務

首先來看一下啓動服務的兩種方式startService和bindService:ide

startService

StartService(Intent intent)spa

start的方式只能簡單的開啓服務,而且開啓以後基本不能勇於服務的運行邏輯,話句話說,開啓後服務就和開啓服務的線程沒什麼關係了。可是一般咱們都是更加緊密的去聯繫服務,可能會獲取一些運行的結果,好比執行結果,進度信息等,那就須要使用bind的方式開啓服務了線程

bindService

bindService地方法就比較豐富,其傳入三處有三個,類型分別爲代理

Intent,ServiceConnection,Int.
其中第一個就不細說了,意圖你們都明白,第二個爲接口,其中包含兩個必須實現的方法:
onServiceConnected(ComponentName var1, IBinder var2)
表明服務鏈接,第一個參數暫且不提,第二個先記住它叫Ibindr,後面會提到。
onServiceDisconnected(ComponentName var1)
表明與服務失去鏈接
第三個參數Int類型就是服務執行的模式。

雖然BindService參數豐富,功能強大,可是其使用邏輯也略微複雜,下面慢慢道來。code

  1. 採用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表明若服務不存在實例則建立實例
  2. 服務內部實現一個代理人類,這個代理繼承自Ibinder,也就是上文ServiceConnection中的onServiceConnected方法的一個返回值,這個Ibinder對象就是服務中的代理在阜外外部的一個引用,經過這個引用就能夠調用Ibinder實現的接口中的方法。繼承

    private class Mybinder extends Binder implements IService{
           //由代理去調用服務內部的方法
           public void callinService(){
               Log.d("phone.....","5.  代理人執行了服務裏的方法");
               @Override
               callInService();
           }
       }
  3. 定義IService的接口接口

    這個接口就是上文提到的IService接口,這個接口中一般定義想要暴露給外部的方法,外部也只能看到IBinder中實現的這個接口的方法,除非你將上一節中的MyBinder這個類定義爲Public。

    public interface IService {
           public void callInService();
       }
  4. 返回代理人對象

    具體服務是如何將IBinder的引用返回給外部呢,就是經過Service惟一的必須實現的方法:

    @Nullable
       @Override
       public IBinder onBind(Intent intent) {
           //當有需求時,呼叫代理人去接待
           Mybinder mybinder=new Mybinder();
           Log.d("phone.....","2.  成功綁定,返回服務的代理對象:"+mybinder.toString());
           return mybinder;
       }
  5. 實現serviceConnection接口裏面的方法

    如今你就能夠在通道中看到Service的代理對象了:

    private class MyConn implements ServiceConnection{
       @Override
       public void onServiceConnected(ComponentName name, IBinder service) {
           myBinder = (IService) service;
           System.out.println("Activity,獲得代理人對象");
       }
  6. 調用接口裏面的方法

    經過MyBinder這個Service的代理對象,就能夠執行服務中對外開放的方法了。固然這個方法就須要你本身去定義了。

    mybinder.callInService();

    繪圖4.jpg

最後的最後,大體說明一下兩種方式開啓服務的特色

startService

  1. 生命週期
    oncreate()--->onstartcommand()--->onstart()--->onDestroy()

  2. 能夠屢次調用,不會重複建立,oncreate()只會執行一次

  3. 以start方式開啓的服務也只能中止一次,屢次調用stopservice()是無效的

  4. 以start方式開啓的服務與UI線程失去關係,即便UI線程被銷燬,服務仍然能夠正常運行

  5. 不能調用服務中的方法

bindService

  1. 生命週期
    oncreate() --->onbind() -->onunbind()---->ondestry();

  2. 只能成功綁定和解綁一次

  3. 與綁定的UI線程同時被銷燬(一根繩上的螞蚱^_^)

  4. 能夠調用服務中的方法

混合開啓服務

既然start開啓的服務不能調用方法,bind方式開啓的服務生命力又很弱,那麼可否兩種方式的有點麼?答案固然是確定的,不然服務的應用能力就太弱了。

  1. 經過startService()方式開啓服務(只能經過調用stopService中止)

  2. 經過bindService進行綁定,以進行服務的方法調用(當須要的時候)

  3. 經過unbindService進行解綁(不須要調用方法了,在UI線程被銷燬以前解綁)

  4. 經過stopService中止服務

這樣咱們就能夠靈活的使用Service,當須要的時候能夠隨時進行調用,不要的時候又能夠長期運行於後臺而不用保留UI線程。這也是服務最多見的用法。

相關文章
相關標籤/搜索