Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android四大組件之Service服務學習筆記(一)

Android四大組件之Service服務學習筆記(一)

編輯:關於Android編程

Service是安卓四大組件之一,服務是用在後台處理事情的,並且是不可見的,該服務不是我們所說的服務器的服務,他經常用來處理一些循環操作,但是它不同於子線程,服務是運行在主線程中的。
  服務一般分為本地服務和遠程服務,這裡先介紹本地服務。
  本地服務通常用兩種啟動方式
  1. 直接啟動模式
    我們可以通過startService(Intent intent)方式去直接啟動一個服務,對於intent意圖,我們也可以用兩種形式
  創建,一種是顯示啟動,一種是隱示啟動,但是需要注意的是,在android5.0以後,所有的服務盡量通過顯示
  意圖來啟動。否則就直接程序崩潰。所以建議都使用顯示方式啟動服務。如果一定要使用隱示啟動方式, 則在對應的intent中添加一句intent.setPackage(對應服務所在的包名),通過這個方法,可以防止5.0後隱示啟動發生崩潰的作用。下面通過代碼來詳細講解下。 
MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
    public void onClick(View view){
        intent = new Intent(this,MyService.class);
        //intent.setPackage("cn.itrealman.servicedemo");5.0以後需要加上這句代碼
        switch (view.getId()) {
            case R.id.start:
                //啟動服務
                startService(intent);
                break;
            case R.id.stop:
                //停止服務
                stopService(intent);
                break;        }
    }
}

在AndroidManifest.xml中配置Service


            
                
                
            
        

MyService.java

public class MyService extends Service {
    public MyService() {
        Log.d("IT_Real", "MyService: 構造方法");
    }

    /**
     * 這個方法是通過綁定的方式才會調用該方法
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("IT_Real", "onBind: ");
        return null;
    }

    /**
     * 服務啟動後初始化內部數據的方法,只會在第一次啟動該服務的時候調用一次
     */
    @Override
    public void onCreate() {
        Log.d("IT_Real", "onCreate: ");
        super.onCreate();
    }

    /**
     * 銷毀服務
     */
    @Override
    public void onDestroy() {
        Log.d("IT_Real", "onDestroy: ");
        super.onDestroy();
    }

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

    /**
     * 這個方法是直接啟動服務時調用的方法,不過該方法已經過時了
     * 被下面的onStartCommand方法代替了
     * @param intent
     * @param startId
     */
    @Override
    public void onStart(Intent intent, int startId) {
        Log.d("IT_Real", "onStart: ");
        super.onStart(intent, startId);
    }

    /**
     * 這個方法也是直接啟動服務時調用的方法
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("IT_Real", "onStartCommand: ");
        return super.onStartCommand(intent, flags, startId);
    }

}

在上面的代碼中,當我們點擊啟動按鈕時,相應的服務被啟動,在此之前,我們先看一下直接啟動方式服務的生命周期圖:
                   這裡寫圖片描述

在上面的圖中,我可以了解到,當我們第一次啟動服務時,會先調用onCreate()——>onStartCommand()——onStart(),然後服務會開始運行,直到調用stopService()方法才會停止服務,然後會調用相應的onDestory()方法,如果服務已經啟動,我們多次點擊啟動服務按鈕,則會多次掉用onStartCommand()——>onStart()方法<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPrbU09rJz8PmtcTV4tbWt73KvaOsztLDx7K7u+G78cihyM66zrf+zvG21M/zo6zSsrK7xNyy2df3yM66zrf+zvHA78PmtcTK/b7do6y2vMrHz7XNs9fUvLrIpbLZ1/e1xKOsvNPI68u1o6zO0sPHtcS3/s7xwO/D5tPQ0ru49mRvU3RoKCm3vbeoo6zO0s/ryKW199PD1eK49re9t6jX9rjDysLH6aOsxMfDtLjD1PXDtLX308PE2KO/1eK49sqxuvKjrM7Sw8e+zda7xNzIpc2ouf3U2m9uU3RhcnRDb21tYW5kKCm3vbeowO/D5siltffTw8HLo6jU2m9uU3RhcnSjqKOpt723qNbQ0rK/ydLUtffTw6OstavKx7K7zca89tXi0fnKudPDo6y5/cqxtcS3vbeoztLE3LK708O+zbK708OjqaOstPrC68jnz8I6PC9jb2RlPjwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> /** * 這個方法也是直接啟動服務時調用的方法 * @param intent * @param flags * @param startId * @return */ @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("IT_Real", "onStartCommand: "); //通過調用該方法 doSth(); return super.onStartCommand(intent, flags, startId); } private void doSth(){ Log.d("IT_Real", "doSth: 我正在做某事..."); }

這樣我們就能完成需要操作的事情了,但是這樣的操作往往會很不方便,不能很好的讓用戶去通過某種方式去操作,比如在播放音樂的時候,我們就會很難去控制服務去處理某些事情,所以一般我們會通過綁定的方式來啟動服務。

  2. 綁定啟動模式
  對於綁定啟動服務,我們可以很好的獲取到服務給我們返回的Ibinder對象,由於Ibinder是一個接口,通常我們會返回一個Ibinder的子類Binder對象。一般情況下,我們會去繼承Binder對象,添加自己所需要的實現功能。綁定啟動的方式是通過bindService(Intent intent, ServiceConnection conn, int flags)綁定服務,該方法的三個參數如下:
  intent:通過Intent指定要啟動的服務
  conn:該參數是一個ServiceConnection對象,該對象用於監聽訪問者與service之間的連接情況。當訪問者與Service直接連接成功時將回調ServiceConnection對象的onServiceConnected(ComponentName name, IBinder service)方法,當Service所在的宿主進程由於異常中斷或者其他原因終止,導致該Service與訪問者之間斷開連接時,會調用ServiceConnection對象的onServiceDisconnected(ComponentName name)方法。
  flags:指定綁定時,是否通過自動創建Service(未創建的情況下),如果該參數指定0(不創建),或者寫BIND_AUTO_CREATE(自動創建)
  創建代碼如下:
MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Intent intent;
    private MyServiceConnection conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        conn = new MyServiceConnection();

    }
    public void onClick(View view){
        intent = new Intent(this,MyService.class);
        switch (view.getId()) {
            case R.id.bindStart:
                bindService(intent,conn,BIND_AUTO_CREATE);
                break;
            case R.id.bindStop:
                unbindService(conn);
                break;        }
    }

    /**
     * ServiceConnection類,通過該類中的onServiceConnected方法
     * 中的IBinder service對象可以獲取到綁定的服務對象中的MyBinder對象
     * 然後可以通過MyBinder對象中的getBindService方法獲取我們的
     * MyBindService對象
     */
    class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //獲取Binder對象
            MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
            MyBindService service2 = service1.getBindService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}

在AndroidManifest.xml中配置Service

 
 

MyBindService.java

public class MyBindService extends Service {
    public MyBindService() {
    }

    /**
     * 返回的IBinder對象
     */
    class MyBinder extends Binder{
        public MyBindService getBindService(){
            returnMyBindService.this;
        }
    }

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

    /**
     * 綁定服務時調用該方法
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("IT_Real", "onBind: ");
        return new MyBinder();
    }


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

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

這樣我們就可以獲取綁定服務對象了。然後我們看一下下面的生命周期圖

                 這裡寫圖片描述

通過綁定服務我們可以看出該生命周期。當調用了bindService方法時,生命周期為onCreate()——>onBind()——>服務運行,當調用unbindService()方法時,服務被關閉,執行onUnbind()——>onDestroy()
通過綁定服務,我們可以獲取到對應的服務對象,如果說要實現某些操作,在服務裡面定義對應的該操作,然後通過服務對象可以去調用該方法。我們去調用一個播放、暫停、上一首、下一首等。代碼如下

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private Intent intent;
    private MyServiceConnection conn;
    private MyBindService service2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        conn = new MyServiceConnection();

    }
    public void onClick(View view){
        intent = new Intent(this,MyBindService.class);
        switch (view.getId()) {
            case R.id.bindStart:
                bindService(intent,conn,BIND_AUTO_CREATE);
                break;
            case R.id.bindStop:
                unbindService(conn);
                break;
            case R.id.startMusic:
                //播放
                service2.start();
                break;
            case R.id.pause:
                //暫停
                service2.pause();
                break;
            case R.id.previous:
                //上一首
                service2.previous();
                break;
            case R.id.next:
                //下一首
                service2.next();
                break;

        }
    }

    /**
     * ServiceConnection類,通過該類中的onServiceConnected方法
     * 中的IBinder service對象可以獲取到綁定的服務對象中的MyBinder對象
     * 然後可以通過MyBinder對象中的getBindService方法獲取我們的
     * MyBindService對象
     */
    class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //獲取Binder對象
            MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
            service2 = service1.getBindService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}

MyBindService.java

public class MyBindService extends Service {
    public MyBindService() {
    }

    /**
     * 返回的IBinder對象
     */
    class MyBinder extends Binder{
        public MyBindService getBindService(){
            return MyBindService.this;
        }
    }

    /**
     * 服務被創建時調用該方法
     */
    @Override
    public void onCreate() {
        Log.d("IT_Real", "onCreate: ");
        super.onCreate();
    }

    /**
     * 綁定服務時調用該方法
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("IT_Real", "onBind: ");
        return new MyBinder();
    }

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

    /**
     * 當調用了unbindService方法是,調用該方法
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("IT_Real", "onUnbind: ");
        return super.onUnbind(intent);
    }

    /**
     * 被關閉之前調用該方法
     */
    @Override
    public void onDestroy() {
        Log.d("IT_Real", "onDestroy: ");
        super.onDestroy();
    }

    public void start(){
        Log.d("IT_Real", "start: 播放");
    }
    public void pause(){
        Log.d("IT_Real", "pause: 暫停");
    }
    public void next(){
        Log.d("IT_Real", "next: 下一首");
    }
    public void previous(){
        Log.d("IT_Real", "previous: 上一首");
    }
}

這樣就可以很好的操作服務裡面的方法了。對於綁定服務,有一個地方需要注意,那就是,我們在啟動服務後,如果退出了當前activity,或者結束該進程的時候,沒有調用unbindService()方法,程序會報一個

Activity cn.itrealman.servicedemo.MainActivity has leaked ServiceConnectioncn.itrealman.service
demo.MainActivity$MyServiceConnection@6c1837b that was originally bound here異常
這個異常表示連接已經綁定,我們沒有解綁,會導致洩露問題。所以,一般我們建議在銷毀Activity時,我們需要在Activity的onDestroy()方法中添加如下代碼:

 @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }

或者說,我們在關閉Activity之前,自己手動調用解綁方法。這樣就能保證我們的程序不出錯。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved