1. 程式人生 > >Android四大元件之Service全面解析(一)

Android四大元件之Service全面解析(一)

 在小杰的上一篇博文中給大家講了一下Android四大元件之一的Activity,也是最重要的,這一篇文章,給大家講一下Service。

什麼是Service

 Service是Android的四大元件之一應用廣泛,它是一個能在後臺進行一個長時間的操作並且不提供使用者介面的一個元件,應用相當廣泛。其他應用元件可以啟動Service,當用戶切換到另一個應用程式時,Service依然可以在後臺執行。

Service的作用

元件能夠繫結到服務與之互動,甚至執行程序間通訊(IPC)。

Service的生命週期

Service有自己的生命週期,它的生命週期方法比Activity少一些,只有onCreate()、onStartCommand()、onDestroy()。

Service的啟動方式以及生命週期

1、通過startService()啟動服務

  • onCreat()                                                                                                                                                                                          當服務第一次建立的時候,優先呼叫onCreat()方法,然後在呼叫onStartCommand()方法,如果說,服務已經啟動,再次呼叫startService()則不會呼叫onCreat()方法,直接呼叫onStartCommand(),onCreat()主要用來做一些初始化的操作。
  • onStartCommand()                                                                                                                                                                             執行一次startService(),就會執行一次onStartCommand(),這個方法很重要,我們在服務進行的後臺操作,比如下載音樂等等,都是在這個方法中進行。
  • onBind()                                                                                                                                                                                              Service中的onBind()方法是抽象方法,Service類本身就是抽象類,所以onBind()方法是必須重寫的,即使我們用不到。
  • onDestory()                                                                                                                                                                                          在銷燬的時候會執行Service的該方法。

2、通過bindService啟動Service

    bindService啟動服務的特點:

  1. 可以繫結多個元件到Service,比如幾個Activity
  2. Activity可以通過IBinder介面來獲取Service的例項,從而呼叫Service中的方法進行互動,通過StartService()啟動Service則不能這樣
  3. 某個元件(Activity)與Service繫結後,當Activity銷燬時自動與Service解除繫結,Activity也可以呼叫UnBindService主動解除繫結。當沒有元件與Service繫結時,Service自動銷燬。
  4. 通過bindService啟動Service不會呼叫onStartCommand()方法。

我們來測試一下,我們寫一個Service:

public class MyService extends Service {
    private final static String TAG = "Service_Text-----";

    /**
     * 建立MyBind,通過getMyService()獲取Service例項
     */
    public class MyBind extends Binder {
        public MyService getMyService() {
            return MyService.this;
        }
    }

    /**
     * 例項化MyBind
     * 通過myBind實現Activity與Service之間的通訊
     */
    MyBind myBind = new MyBind();

    /**
     * @param intent
     * @return 在onBind中返回MyBind
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return myBind;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: " + intent.getStringExtra("activity"));
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: MyService" );
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: "+ intent.getStringExtra("activity"));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: MyService" );
    }
}

在寫兩個Activity ,ActivityA ActivityB

public class ActivityA extends AppCompatActivity implements View.OnClickListener {
    private final static String TAG = "Service_Text-----";
    private Service mService = null;
    private boolean isBind = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        findViewById(R.id.btn1).setOnClickListener(this);
        findViewById(R.id.btn2).setOnClickListener(this);
        findViewById(R.id.btn3).setOnClickListener(this);
        findViewById(R.id.btn4).setOnClickListener(this);

    }

    /**
     * 繫結Service後,會執行ServiceConnection,可以通過onServiceConnected中的IBinder獲取Service例項
     */
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            isBind = true;
            MyService.MyBind myBind = (MyService.MyBind) service;
            //獲取Services例項
            mService = myBind.getMyService();
            Log.d(TAG, "onServiceConnected: ------------------------Activity A");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.d(TAG, "onServiceDisconnected: ------------------------Activity A");
        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                //繫結Service
                Intent intent = new Intent(this, MyService.class);
                intent.putExtra("activity", "Activity_A");
                Log.d(TAG, "Activity A------執行了bindService");
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                break;
            case R.id.btn2:
                if (isBind) {
                    Log.d(TAG, "Activity A------unbindService");
                    unbindService(serviceConnection);
                }
                break;
            case R.id.btn3:
                Intent intent1 = new Intent(this, ActivityB.class);
                startActivity(intent1);
                Log.d(TAG, "Activity A------跳轉到了B");
                break;
            case R.id.btn4:
                finish();
                Log.d(TAG, "Activity A------結束");
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "ActivityA - onDestroy");
    }
}
public class ActivityB extends AppCompatActivity implements View.OnClickListener{
    private final static String TAG = "Service_Text-----";
    private Service mService = null;
    private boolean isBind = false;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        findViewById(R.id.btn1).setOnClickListener(this);
        findViewById(R.id.btn2).setOnClickListener(this);
        findViewById(R.id.btn3).setVisibility(View.GONE);
        findViewById(R.id.btn4).setOnClickListener(this);
    }
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            isBind = true;
            MyService.MyBind myBind = (MyService.MyBind) service;
            //獲取Services例項
            mService = myBind.getMyService();
            Log.d(TAG, "onServiceConnected: ------------------------Activity B");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.d(TAG, "onServiceDisconnected: ------------------------Activity B");
        }
    };
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                //繫結Service
                Intent intent = new Intent(this, MyService.class);
                intent.putExtra("activity", "Activity_B");
                Log.d(TAG, "Activity B------執行了bindService");
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                break;
            case R.id.btn2:
                if (isBind) {
                    Log.d(TAG, "Activity B------unbindService");
                    unbindService(serviceConnection);
                }
                break;
            case R.id.btn4:
                finish();
                Log.d(TAG, "Activity B------結束");
                break;
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Activity B - onDestroy");
    }
}

OK,現在我們執行專案啟動ActivityA

我們點選bindService,可以看到控制檯的輸出:

我們點選UnBindService按鈕,控制檯輸出:

我們點選bindService後點擊finish,控制檯輸出:

我們在Activity中bindService後在跳轉到ActivityB,在ActivityB中bindService

我們在點選unBindService:

我們在ActivityB中點選bindService後點擊finish:

這時我們回到ActivityA了,service還存在,我們在點選finish:

Service銷燬了

測試總結

 經過上述的測試,我們來總結一下,當我們通過bindService繫結Service後,Service啟動,並且會回撥onServiceConnected()方法,我們可以通過這個回撥獲取到Service例項從而進行一些Service裡面的操作。Service可以繫結多個Activity,連續多次呼叫bindService除第一次外其他繫結操作則沒有任何方法執行(因為已經是繫結狀態,不會重複繫結)。第一個繫結Service時,因為Service是首次繫結,所以Service會執行onCreat()方法,然後onBind(),onServiceConnected(),而後面的Activity執行BindService的時候,Service只會執行onServiceConnected()。當Activity與Service解除繫結是,會呼叫onUnBind(),當Service沒有繫結的Activity時,會執行onUnBind(),OnDestory()。