Android-服務(wù)Service

Service介紹

Service(服務(wù))是一個(gè)可以再后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而沒(méi)有用戶界面的應(yīng)用組件。服務(wù)可用其他應(yīng)用組件啟動(dòng),服務(wù)一旦被啟動(dòng)將在后臺(tái)一直運(yùn)行,即使啟動(dòng)服務(wù)的組件銷(xiāo)毀也不會(huì)影響它。
比如:服務(wù)可以處理網(wǎng)絡(luò)請(qǐng)求,播放音樂(lè),執(zhí)行文件I/O等,一切都可以在后臺(tái)運(yùn)行。
服務(wù)的兩種形式:

  • 啟動(dòng)狀態(tài)
    應(yīng)用組件調(diào)用startService()啟動(dòng)服務(wù),服務(wù)就處于‘啟動(dòng)’狀態(tài),就可以在后臺(tái)一直運(yùn)行,除非手動(dòng)停止服務(wù)
  • 綁定狀態(tài)
    當(dāng)應(yīng)用組件通過(guò)調(diào)用bindService()綁定服務(wù)時(shí),服務(wù)處于‘綁定’狀態(tài)。綁定服務(wù)提供一個(gè)客戶端-服務(wù)的接口,運(yùn)行組件和服務(wù)進(jìn)行交互。

Service使用

定義服務(wù)

public class MyTestService extends Service {

    public static final String TAG = "MyTestService";

    public MyTestService() {
    }

    /**
     * 首次創(chuàng)建服務(wù)時(shí),系統(tǒng)會(huì)執(zhí)行一次onCreate;
     * 如果服務(wù)已經(jīng)啟動(dòng),不會(huì)再調(diào)用
     */
    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        super.onCreate();
    }

    /**
     * 每次調(diào)用startService()方法啟動(dòng)服務(wù)都會(huì)被調(diào)用
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 綁定服務(wù)(bindService)時(shí)才會(huì)調(diào)用
     * 把Binder返回客戶端,對(duì)應(yīng)onServiceConnected的IBinder
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return new MyBinder();
    }

    /**
     * 解除綁定時(shí)回調(diào)
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    /**
     * 服務(wù)銷(xiāo)毀時(shí)回調(diào)
     */
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        super.onDestroy();
    }

    /**
     * 服務(wù)內(nèi)定義的方法,提供外部調(diào)用
     */
    public void testMethod(){
        Log.d(TAG, "testMethod");
    }

    /**
     * 定義Binder對(duì)象,返回客戶端使用,內(nèi)部定義了一個(gè)返回服務(wù)實(shí)例的方法
     */
    class MyBinder extends Binder{
        /**
         * 返回本服務(wù)實(shí)例(給客戶端調(diào)用)
         * @return
         */
        public MyTestService getServer(){
            // 返回服務(wù)對(duì)象,這樣客戶端就可以調(diào)用服務(wù)的公共方法了
            return MyTestService.this;
        }
    }
}

清單定義(應(yīng)用組件都需要在清單中定義Activity,Service, Receiver, Provider):

<service android:name=".MyTestService" android:enabled="true" android:exported="true"/>

啟動(dòng)服務(wù)/停止服務(wù):

startService(new Intent(this, MyTestService.class));
stopService(new Intent(this, MyTestService.class));

服務(wù)生命周期:
onCreate() -> onStartCommand() -- 服務(wù)啟動(dòng) -- onDestory()

應(yīng)用設(shè)置那邊可以看到運(yùn)行的服務(wù):


image.png

綁定服務(wù)和解除綁定:

Intent intent = new Intent(this, MyTestService.class);
bindService(intent, cnn, BIND_AUTO_CREATE);

/**
 * ServiceConnection代表與服務(wù)的連接,
 * onServiceConnected代表連接一個(gè)服務(wù)成功后被調(diào)用,IBinder返回服務(wù)的onBinder的對(duì)象
 * onServiceDisconnected是在服務(wù)崩潰或被殺死導(dǎo)致的連接中斷時(shí)被調(diào)用,一般不會(huì)被調(diào)用
 */
ServiceConnection cnn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Log.d("###", "onServiceConnected");
        // 獲取Binder對(duì)象
        MyTestService.MyBinder binder = (MyTestService.MyBinder)iBinder;
        // 調(diào)用Binder的方法,返回服務(wù)實(shí)例
        myTestService = binder.getServer();
        // 調(diào)用服務(wù)的方法
        myTestService.testMethod();
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.d("###", "onServiceDisconnected");
    }
};

unbindService(cnn); // 解除綁定

生命周期:
onCreate() -> onBind() -> 服務(wù)綁定 -> onUnbind() -> onDestory()

使用綁定服務(wù),都是為了調(diào)用服務(wù)的方法,因此在不需要的時(shí)候及時(shí)解綁防止內(nèi)存泄漏。

附上一張綁定邏輯圖:


image.png

注意:

  1. 這種綁定服務(wù)的方式,需要和服務(wù)在同一個(gè)進(jìn)程中,否則會(huì)調(diào)用失敗。
    我們把服務(wù)設(shè)置一個(gè)進(jìn)程名::mytestservice表示包名:mytestservice
        <service
            android:name=".MyTestService"
            android:enabled="true"
            android:exported="true"
            android:process=":mytestservice"/>

startService啟動(dòng)服務(wù)的方式還是可以的,日志都打在服務(wù)的進(jìn)程上了。

image.png

而使用綁定的方式出現(xiàn)異常:
image.png

此時(shí)跨進(jìn)程的方式需要使用MessengerAIDL.

  1. 服務(wù)的執(zhí)行代碼是在主線程上的,因此不能處理太耗時(shí)的操作。如果需要耗時(shí)操作,還是需要?jiǎng)?chuàng)建線程,或者可以使用IntentService.

參考:

https://blog.csdn.net/javazejian/article/details/52709857

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 【Android Service】 Service 簡(jiǎn)介(★★★) 很多情況下,一些與用戶很少需要產(chǎn)生交互的應(yīng)用程...
    Rtia閱讀 3,237評(píng)論 1 21
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情況下的生命周期:在用戶參與的情況下...
    AndroidMaster閱讀 3,280評(píng)論 0 8
  • #組件 * Activity * broadcast Receiver * Service : 服務(wù) > wind...
    未聞椛洺閱讀 790評(píng)論 0 0
  • 前言:本文所寫(xiě)的是博主的個(gè)人見(jiàn)解,如有錯(cuò)誤或者不恰當(dāng)之處,歡迎私信博主,加以改正!原文鏈接,demo鏈接 Serv...
    PassersHowe閱讀 1,520評(píng)論 0 5
  • 9月1日 開(kāi)心的三件事兒 1. 一天順順利利度過(guò)了。 2. 氣溫下降了。夏天沒(méi)怎么體會(huì)到就過(guò)去。今年給人的感覺(jué)是,...
    七不斯閱讀 370評(píng)論 0 0

友情鏈接更多精彩內(nèi)容