Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android四大組件之一:Service

Android四大組件之一:Service

編輯:關於Android編程

一:Service的概述
Service是Android四大組件中與Activity最相似的組件。都代表執行的程序,Service與Activity的區別在於:
Service一直在後台運行,它沒有用戶界面,所以絕不會到前台來。一旦Service被啟動起來之後,它就與Activity一樣。完全具有自己的生命周期。
關於程序中Activity和service的選擇標准:
如果某個程序組件需要在運行時向用戶呈現某種界面,或者該程序需要與用戶交互,就需要使用Activity,否則就應該考慮使用Service了。
如:下載東西,播放音樂。可以一邊下載,一邊播放,一邊玩其他的事情。但是Activity是無法做到的。只要Activity被關閉或者最小化了,程序就停止了。

二:特點
1.沒有UI
2.進行耗時較長或者與用戶沒有交互的一些功能
3.Service具有較高的優先級,比stop的Activity優先級要高,最高的優先級是前台Activity
4.具有較長的生命周期

三:Service的使用
1)創建:
創建類繼承Service,實現OnBind()方法。
Service與Activity都是從Context派生出來的。
因此可以使用Context中的方法,如getResouces()等方法。
2)配置:
在配置文件中配置標簽
設置android:name屬性,也可以配置元素

3)啟動:
Service啟動依賴於其他組件,可以使用Activity或者Receiver等作為調用者,調用者可以使用以下兩種形式啟動Service
(1)startService
startService啟動Service涉及生命周期方法:
onCreate()–onStartCommand()/onStart()–onDestory()
a)onCreate()創建Service實例時的回調函數,啟動的Service實例如果不存在會觸發一次之後不會觸發.
b)onStartCommand() 啟動Service時的回調函數每次啟動都會觸發,可以通過參數startId獲取其啟動次數,第二個參數flags表示啟動服務的方式:
c)onStart():啟動Service時,已經被淘汰了。
d)onDestory():銷毀Service實例

注意:
onStartCommand()的返回值用來指定Service的系統在用戶為手動關閉Service前自動回收Service資源了Service資源情況下的重啟行為:
a)START_STICKY
如果service進程被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent對象。隨後系統會嘗試重新創建service,由於服務狀態為開始狀態,所以創建服務後一定會調用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那麼參數Intent將為null。
b)START_NOT_STICKY
“非粘性的”。如果在執行完onStartCommand後,服務被異常kill掉,系統不會自動重啟該服務。
c)START_REDELIVER_INTENT
使用這個返回值時,如果在執行完onStartCommand後,服務被異常kill掉,系統會自動重啟該服務,並將Intent的值傳入。
d)START_STICKY_COMPATIBILITY:
START_STICKY的兼容版本,但不保證服務被kill後一定能重啟。

該方法用來啟動一個獨立的Service實例,
該實例與調用者沒有關聯關系
調用者的生命周期不會影響到Service的生命周期
即使訪問者退出了,Service仍然運行。

(2)bindService
該方法用來將一個Service實例與調用者建立關聯關系,Service與調用者之間可以進行數據共享,調用者聲明周期會影響的Service的生命周期,即使訪問者退出了Service也就終止
bindService方法有三個參數:
第一個參數包含要綁定Service信息的Intent對象
第二個參數是一個ServiceConnection對象,該對象用於監聽訪問者與Service之間的連接情況。當訪問者與Service之間鏈接成功時將回調該ServiceConnection對象的onServiceConnected(ComponentName,IBinder)方法;當Service所在的宿主進程由於異常中止或由於其他原因終止,導致該Service與訪問者之間斷開連接時回調該ServiceConnection對象的onServiceDisconnected(ComponentName)方法。其中onServiceConnected方法中的IBinder對象,可實現與被綁定Service之間的通信。在開發Service類時,該Service類必須提供一個IBinder onBind()方法,該方法所返回的IBinder對象將會傳給ServiceConnection對象裡onServiceConnected方法的參數中。這樣訪問者就
可以通過該IBinder對象與Service進行通信。實際開發時通常會采用繼承Binder(IBinder的實現類)的方式實現自己的IBinder對象。
第三個參數指定綁定時是否自動創建Service
(如果Service還未創建),該參數可指定為0(不自動創建)
或BIND_AUTO_CREATE(自動創建)。

 bindService啟動Service的生命周期方法:
 onCreate()--->onBind()--->onUnbind()--->onDestory().

a)onCreate() 同startService
b)onBind() 在Service與調用者建立關聯關系時使用,該方法會返回一個IBinder類型的實例給調用者,作為Service在調用者的代理.

c)onUnbind() Service與調用者解除綁定。
d)onDestory() 同startService
e)onRebind() 重新連接

5)停止:針對不同啟動方式,可以使用兩種方式在調用者中手動關閉Service
stopService(Intent it);
unbindService(ServiceConnection conn)

6)IntentService
Android中的Service是用於後台服務的,當應用程序被掛到後台的時候,問了保證應用某些組件仍然可以工作而引入了Service這個概念,那麼這裡面要強調的是Service不是獨立的進程,也不是獨立的線程,它是依賴於應用程序的主線程的,也就是說,在更多時候不建議在Service中編寫耗時的邏輯和操作,否則會引起ANR(Application Not Responding)。那麼我們當我們編寫的耗時邏輯,不得不被service來
管理的時候,就需要引入IntentService,IntentService是繼承Service的,那麼它包含了
Service的全部特性,當然也包含service的生命周期,那麼與service不同的是,IntentService在執行onCreate操作的時候,內部開了一個線程,去你執行你的耗時操作。該線程保證同一時刻只處理一個Intent.這樣IntentService不會阻塞主線程。
IntentService的使用和Service是類似。它需要重寫onHandleIntent(Intent intent)方法。

注意:service 沒有unbind時was originally bound here錯誤。
在程序中,如果在activity中綁定了服務,
而沒有在destory中,寫unbind,會出現這種異常,
解決方式:在Activity的onDestory方法中調用unbindService(sc)
方法,該方法是context中的方法。

package com.xspacing.service;

import com.xspacing.service.SecondService.MyBinder;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

    private Intent intent;
    private Intent intent2;
    private BindServiceConnection conn;

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

    public void startService(View v) {
        intent = new Intent(this, FirstService.class);
        // 啟動服務
        // 通過這個方式啟動的服務,這個服務的生命周期不受activity的生命周期的影響
        startService(intent);
    }

    public void stopService(View v) {
        stopService(intent);
    }

    public void startBindService(View v) {
        intent2 = new Intent(this, SecondService.class);
        conn = new BindServiceConnection();
        // 通過這個方式啟動的服務,這個服務的生命周期與activity的生命周期息息相關的
        bindService(intent2, conn, BIND_AUTO_CREATE);
    }

    public void stopBindService(View v) {
        // stopService(intent);
        unbindService(conn);
        conn=null;
    }
    public void intentService(View v) {
        Intent intent = new Intent(this, MyItentService.class);
        startService(intent);
    }


    class BindServiceConnection implements ServiceConnection {

        private static final String TAG = "BindServiceConnection";

        // service與activity進行綁定的時候會回調
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(TAG, "onServiceConnected()");
            MyBinder binder=(MyBinder) service;
            int count = binder.getCount();
            Log.i(TAG, count+"");
        }

        // service與activity異常解除綁定的時候會回調
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected()");
        }

    }

    @Override
    protected void onDestroy() {
        if (conn != null) {
            unbindService(conn);
        }
        super.onDestroy();
    }
}
package com.xspacing.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * @ClassName FirstService.java
 * @Description Service生命周期
 * @author smile
 * @version v1.0
 * @date 2016年10月8日
 */
public class FirstService extends Service {

    private static final String TAG = "FirstService";
    private boolean flag;
    private int count;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 開啟了再開啟只執行一次
     */
    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate()");
        flag = true;
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (flag) {
                    count++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i(TAG, count + "");
                }
            }
        }).start();
        super.onCreate();
    }

    /**
     * 開啟了再開啟每次執行一次
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy()");
        flag = false;
        super.onDestroy();
    }

}
package com.xspacing.service;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class MyItentService extends IntentService {

    private static final String TAG = "MyItentService";
    private int count;
    private boolean flag = true;

    public MyItentService(String name) {
        super(name);
    }

    public MyItentService() {
        this("MyItentService");
    }

    /**
     * 底層開辟了一個子線程
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        while (flag) {
            count++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, count + "");
        }
    }

    @Override
    public void onDestroy() {
        flag = false;
        super.onDestroy();
    }

}
package com.xspacing.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class SecondService extends Service {

    private static final String TAG = "SecondService";
    private int count;
    boolean flag;

    @Override
    public IBinder onBind(Intent intent) {

        return new MyBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate()");
        Log.i(TAG, "onBind()");
        flag = true;
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (flag) {
                    count++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i(TAG, count + "");
                }
            }
        }).start();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "onUnbind()");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy()");
        flag = false;
        super.onDestroy();
    }

    // 通常自己實現一個類繼承Binder,也間接地實現了IBinder接口
    public class MyBinder extends Binder {
        public int getCount() {
            return count;
        }
    }

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