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匹舞。
分析:
- 通過startService啟動(dòng)的服務(wù)必須使用stopService停止。
- 通過bindService啟動(dòng)的服務(wù)必須使用unBindService停止叫榕。
- 不管是通過哪種方式啟動(dòng)的service首次會(huì)執(zhí)行onCreate姊舵。
- 不管是通過哪種方式啟動(dòng)的service再次啟動(dòng)還是按自身的生命周期執(zhí)行,startService(多次onStartCommand)荞下,bindService(一次onBind).
- 停止的時(shí)候必須調(diào)用兩種方式自身的關(guān)閉事件才能完成整個(gè)生命周期史飞。(startService-stopService),(bindService-unBindService).
- 因?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
- 關(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;
}
}
- 因?yàn)閕ntentService里面是個(gè)消息隊(duì)列,所以隊(duì)列里面有消息的時(shí)候再添加消息虐唠,也是同一個(gè)線程在執(zhí)行凿滤。
- 在工作線程中調(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方法.
- 列外還有一個(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());
}
}
}