service

service是運(yùn)行在ui線程中的一個(gè)服務(wù)黍析,不是一個(gè)線程也不是一個(gè)進(jìn)程橄仍。

啟動(dòng)

startService(intent);

該方式啟動(dòng)的Service會(huì)一直在后臺(tái)運(yùn)行,如果沒關(guān)閉service的話侮繁,即使activity關(guān)閉還是在后臺(tái)運(yùn)行宪哩。也就是說啟動(dòng)service后就和當(dāng)前的activity沒關(guān)系了。

bindService(intent,ServiceConnection,flag);

方式啟動(dòng)的service是和當(dāng)前的activity有綁定關(guān)系的彬祖,如果當(dāng)前activity關(guān)閉并且沒有unBind會(huì)拋出一個(gè)異常:android.app.ServiceConnectionLeaked: Activity xxx.MyActivity has leaked ServiceConnection.但是這個(gè)異常對(duì)前臺(tái)沒影響品抽。

生命周期

startService

Context.startService啟動(dòng):onCreate -> onStartCommand(onStart)
Context.stopService停止: onDestroy

1.多次啟動(dòng)service的話圆恤,只會(huì)執(zhí)行一次onCreate,會(huì)多次執(zhí)行onStartCommand方法(service沒有被Destroy).
2.如果不手動(dòng)關(guān)閉service的話,service會(huì)一直運(yùn)行羽历。除非調(diào)用stopServic())或者service執(zhí)行完業(yè)務(wù)后通過stopSelf()關(guān)閉自己。
3.如果service中啟動(dòng)了一個(gè)線程诵闭,關(guān)閉service后澎嚣,如果線程沒有執(zhí)行完的話還會(huì)繼續(xù)執(zhí)行,所以關(guān)閉service的時(shí)候一定要確保service中的業(yè)務(wù)已執(zhí)行完成或者關(guān)閉润歉。

bindService

onCreate -> onBind ->onUnbind(onReBind) ->onDestroy
bindService: onCreate -> onBind
unbindService: onUnbind -> onDestroy

1.多次綁定service的話颈抚,不會(huì)執(zhí)行任何生命周期(service在bind狀態(tài)),只會(huì)bind一次驱富。
2.onReBind只會(huì)在混合啟動(dòng)時(shí)觸發(fā)

混合啟動(dòng)

一個(gè)service啟動(dòng)時(shí)使用了startService和bindService匹舞。
分析:

  1. 通過startService啟動(dòng)的服務(wù)必須使用stopService停止。
  2. 通過bindService啟動(dòng)的服務(wù)必須使用unBindService停止叫榕。
  3. 不管是通過哪種方式啟動(dòng)的service首次會(huì)執(zhí)行onCreate姊舵。
  4. 不管是通過哪種方式啟動(dòng)的service再次啟動(dòng)還是按自身的生命周期執(zhí)行,startService(多次onStartCommand)荞下,bindService(一次onBind).
  5. 停止的時(shí)候必須調(diào)用兩種方式自身的關(guān)閉事件才能完成整個(gè)生命周期史飞。(startService-stopService),(bindService-unBindService).
  6. 因?yàn)閟tartService沒有onStop,是執(zhí)行的onDestroy,所以只有最后一個(gè)關(guān)閉事件才會(huì)觸發(fā)onDestroy事件构资。如果stopService不是最后一個(gè)關(guān)閉的話就不會(huì)觸發(fā)service的生命周期。
    測(cè)試日志:
// bind -> start
...bind click 1
....MyService onCreate=1
....MyService onBind=1
...onServiceConnected 1
...start click 1
....MyService onStartCommand=1
....MyService onStart=1
//start -> bind
...start click 1
....MyService onCreate=1
....MyService onStartCommand=1
....MyService onStart=1
...bind click 1
....MyService onBind=1
...onServiceConnected 1
// stop -> unbind
...stop click 1
...unbind click 1
....MyService onUnbind=1
....MyService onDestroy=1
// unbind -> stop
...unbind click 1
....MyService onUnbind=1
...stop click 1
....MyService onDestroy=1
  1. 關(guān)于onReBind, 要滿足兩個(gè)條件:
    ->onUnbind返回true,onReBind method later called when new clients bind to it迹淌。
    ->通過混合啟動(dòng)。如果僅僅是bindService啟動(dòng)的話,一unBind就destroy了荷鼠。
    這樣的話如果unBind后允乐,再次點(diǎn)擊綁定就會(huì)執(zhí)行onReBind.如果 onUnbind返回false,進(jìn)行unBind后蠢笋,再次綁定不會(huì)執(zhí)行任何生命周期(直接建立ServiceConnection連接進(jìn)行訪問的服務(wù)鳞陨,不會(huì)執(zhí)行service的生命周期).
// onUnbind ->false
...bind click 1
....MyBinder getService=1
....MyService dosomething=1
...onServiceConnected 1
....MyBinder something=1
// onUnbind ->true
...bind click 1
....MyBinder getService=1
....MyService dosomething=1
...onServiceConnected 1
....MyBinder something=1
....MyService onRebind=1

不被回收處理

cpu休眠處理

IntentService

在service中創(chuàng)建了一個(gè)線程(HandlerThread)挂绰,用來異步加載籽慢。執(zhí)行完成后會(huì)自動(dòng)關(guān)閉服務(wù)对供。

public abstract class IntentService extends Service{
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
}

其使用方法和普通service沒區(qū)別趟咆,唯一的不同就是自身?yè)碛幸粋€(gè)異步方法(onHandleIntent)。

public class BaseIntentService extends IntentService {
    private final String TAG = "BaseIntentService";

    BaseIntentServiceBinder mBinder = new BaseIntentServiceBinder();

    public BaseIntentService() {
        super("isname");

    }

    @Override
    protected void onHandleIntent(Intent intent) {

        int order = intent.getIntExtra("order",-1);
        Log.d(TAG, "BaseIntentService onHandleIntent order="+order);
        Log.d(TAG, "BaseIntentService onHandleIntent thread->" + Thread.currentThread().getId()+",order="+order);
        try {
            Log.d(TAG, "BaseIntentService onHandleIntent do somethings...order="+order);
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "BaseIntentService onHandleIntent done order="+order);

    }

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

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

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

    @Override
    public void onCreate() {
        Log.d(TAG, "BaseIntentService onCreate");
        super.onCreate();
        Log.d(TAG, "BaseIntentService onCreate thread->" + Thread.currentThread().getId());
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "BaseIntentService onBind");
        //        return super.onBind(intent);
        return mBinder;
    }

    public class BaseIntentServiceBinder extends Binder {
        public int testMethod(int num) {
            return num;
        }
    }

  1. 因?yàn)閕ntentService里面是個(gè)消息隊(duì)列,所以隊(duì)列里面有消息的時(shí)候再添加消息虐唠,也是同一個(gè)線程在執(zhí)行凿滤。
  2. 在工作線程中調(diào)用該方法。每一個(gè)時(shí)刻只能處理一個(gè)intent請(qǐng)求翁脆,當(dāng)同時(shí)有多個(gè)intent請(qǐng)求時(shí)反番,也就是客戶端同時(shí)多次調(diào)用Content#startService方法啟動(dòng)同一個(gè)服務(wù)時(shí)叉钥,這些請(qǐng)求就會(huì)放于消息隊(duì)列中篙贸,直到前面的intent異步任務(wù)請(qǐng)求處理完成才會(huì)處理下一個(gè)intent請(qǐng)求。直到所有的intent請(qǐng)求結(jié)束之后敷鸦,IntentService服務(wù)會(huì)調(diào)用stopSelf停止當(dāng)前服務(wù)寝贡。也就是當(dāng)intent異步任務(wù)處理結(jié)束之后,對(duì)應(yīng)的IntentService服務(wù)會(huì)自動(dòng)銷毀碟案,進(jìn)而調(diào)用IntentService#onDestroy方法.
  3. 列外還有一個(gè)問題颇蜡,這里onHandleIntent后就執(zhí)行stopSelf,為什么請(qǐng)求多次的時(shí)候,第一次執(zhí)行完沒有stop熔任,而是一直再遍歷消息唁情。這里要看service啟動(dòng),停止的源碼進(jìn)行分析(啟動(dòng)服務(wù)的時(shí)候如果服務(wù)已經(jīng)存在則會(huì)將該請(qǐng)求添加到ServiceRecord.deliveredStarts中惦费,參照service的啟動(dòng)ActiveServices.sendServiceArgsLocked()).

service測(cè)試代碼

public class MyService extends Service {

    private boolean keepalive = false;
    private MyBinder binder = new MyBinder();

    private int count = 0;

    private Thread mThread;

    @Override
    public IBinder onBind(Intent intent) {
        LogUtil.debug("....MyService onBind=" + Thread.currentThread().getId());

        return binder;
    }

    @Override
    public void onCreate() {
        LogUtil.debug("....MyService onCreate=" + Thread.currentThread().getId());
        super.onCreate();
        doBussness();
    }

    @Override
    public void onDestroy() {
        LogUtil.debug("....MyService onDestroy=" + Thread.currentThread().getId());

        super.onDestroy();
        if (keepalive) {
            stopForeground(true);
        }

        if(mThread != null && mThread.isAlive()){
            LogUtil.debug("....MyService onDestroy thread isAlive");
            mThread.interrupt();
        }else{
            LogUtil.debug("....MyService onDestroy thread not alive");
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        LogUtil.debug("....MyService onUnbind=" + Thread.currentThread().getId());
//        return super.onUnbind(intent);
        return true;
    }

    @Override
    public void onRebind(Intent intent) {
        LogUtil.debug("....MyService onRebind=" + Thread.currentThread().getId());
        super.onRebind(intent);
    }

    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        LogUtil.debug("....MyService onStart=" + Thread.currentThread().getId());
        if (keepalive) {
            LogUtil.debug("....MyService startForeground=" + Thread.currentThread().getId());
            startForeground(0, null);
        }


    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtil.debug("....MyService onStartCommand=" + Thread.currentThread().getId());

        return super.onStartCommand(intent, flags, startId);
    }

    private void doBussness() {

        if(mThread != null && mThread.isAlive()){
            return;
        }
        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!mThread.isInterrupted()) {
                    LogUtil.debug("count=" + count);
                    try {
                        Thread.sleep(1000);
                        count++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        mThread.interrupt();
                    }
                }
            }
        });
        mThread.start();
    }

    public void dosomething() {
        LogUtil.debug("....MyService dosomething=" + Thread.currentThread().getId());
    }

    class MyBinder extends Binder {

        public MyService getService() {
            LogUtil.debug("....MyBinder getService=" + Thread.currentThread().getId());
            return MyService.this;
        }

        public void something() {
            LogUtil.debug("....MyBinder something=" + Thread.currentThread().getId());
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刻恭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鞍匾,更是在濱河造成了極大的恐慌骑科,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梁棠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡凫海,警方通過查閱死者的電腦和手機(jī)男娄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人围橡,你說我怎么就攤上這事缕贡。” “怎么了收擦?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵谍倦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我宴猾,道長(zhǎng)叼旋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任讹剔,我火速辦了婚禮详民,結(jié)果婚禮上沈跨,老公的妹妹穿的比我還像新娘。我一直安慰自己谒出,他們只是感情好邻奠,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布碌宴。 她就那樣靜靜地躺著蒙畴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碑隆。 梳的紋絲不亂的頭發(fā)上蹬音,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天著淆,我揣著相機(jī)與錄音,去河邊找鬼永部。 笑死,一個(gè)胖子當(dāng)著我的面吹牛懦砂,可吹牛的內(nèi)容都是我干的组橄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼衫画,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瓮栗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弥激,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤微服,失蹤者是張志新(化名)和其女友劉穎缨历,沒想到半個(gè)月后糙麦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丛肮,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宝与,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咆瘟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诽里。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡须肆,死狀恐怖桩皿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泄隔,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布逻澳,位于F島的核電站斜做,受9級(jí)特大地震影響湾揽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜库物,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一戚揭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧精居,春花似錦、人聲如沸箱蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辈毯。三九已至,卻和暖如春钝凶,著一層夾襖步出監(jiān)牢的瞬間唁影,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工哟沫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锌介,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓隆敢,卻偏偏與公主長(zhǎng)得像崔慧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子温自,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容