Android中Service生命周期


這幾天面試的時候,反復被問到一個關於Service的問題。

之前做了一個APP。有一個應用場景是,需要開機啟動一個Service,在Service中另開一個線程,去對比用戶配置中的時間,作出及時提醒。

然后面試的時候在描述該做法時就被問到一個問題,如果Service被系統或者其他應用kill了怎么辦?我當時的回答是,在onDestroy中去處理。面試官說,onDestroy並不會被調用。

面試的詳情暫且不表,在后期會專門寫面經。現在討論這個問題,Service被kill后生命周期是怎樣的。

OK,用代碼說話。

1,新建一個項目,項目中有一個Activity,一個Service。在Activity的button的監聽處理中去開啟這個Service

MainActivity.java

package com.zhenghuiy.killedservicelifecycletest;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{
	private Button startServiceBtn;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initViews();
	}

	private void initViews() {
		startServiceBtn = (Button) findViewById(R.id.startService);
		startServiceBtn.setOnClickListener(this);
	}

	@Override
	public void onClick(View view) {
		if(view.getId() == R.id.startService){
			Intent intent = new Intent();
			intent.setClass(this, MyService.class);
			this.startService(intent);
		}
			
		
	}


}

  

 

2,重寫Service的大部分函數,具體看注釋

MyService.java

package com.zhenghuiy.killedservicelifecycletest;

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

public class MyService extends Service implements Runnable{
	/*
	 * Service當以bindService的形式調用時,會調用onBind
	 * 當以startService,則調用onStartCommand
	 * 另外,onBind是一個抽象函數,必須重寫
	 * */
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		showLog("onStartCommand is called");
		
		//Service運行在UI主線程,為了避免因堵塞而被關閉,另開一個線程
		new Thread(this).start();
		
	
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent itent) {
		showLog("onBind is called");
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		showLog("onCreate is called");
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		showLog("onDestroy is called");
	}

	/*
	 * onStart方法已經過時
	 * 在2.0之后的版本使用onStartCommand
	 * */
	@Override
	@Deprecated
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		showLog("onStart is called,the Intent action is"+intent.getAction());
	}

	@Override
	public void onTaskRemoved(Intent rootIntent) {
		super.onTaskRemoved(rootIntent);
		showLog("onTaskRemoved is called,the Intent action is"+rootIntent.getAction());
	}

	@Override
	public void onTrimMemory(int level) {
		super.onTrimMemory(level);
		showLog("onTrimMemory is called,the level is"+level);
	}
	
	private void showLog(String text){
		Log.v(this.getClass().getName(),text);
	}

	@Override
	public void run() {
		while(true){}
	
	}
}

  

3,用真機測試

運行后點擊button,啟動service,此時以下函數被調用:

點擊home回到手機桌面,此時該Service仍然在后台運行。onTrimMemory被調用

我使用的手機是華為3C。進入系統的setting后,可以看到顯示該應用有一個進程和一個服務在運行中。

在設置里的應用管理那點擊“停止”。onDestroy被調用

說明,當服務被系統自動或手動(人為的在設置里停止)停止時,仍然會正常走完其生命周期。

4,測試使用其他應用,比如“騰訊手機管家”去停止Service.

前面同樣的過程就不贅述,當Service在后台運行的時候,使用手機管家去“一鍵加速”。

可以在設置——》應用管理 里看到,原來該測試應用的item顯示“有1個進程和1個服務在運行”變成“有0個進程和1個服務在運行”。再刷新一遍,就發現,該應用已經不在運行中的列表里了。

並且,logcat里始終沒有打印“onDestroy is called”.

結論是,其他“管家式”應用“清理”的方法是,直接kill該進程。此時,Service不會走正常的生命周期,也就是onDestroy未被調用。

5,回到問題本身

當時面試官問Service的onDestory並不會被調用,此時你要如何解決。我的回答是:

一種方法是,使用服務器進行推送。如果客戶端有響應,說明Service存活。如果沒有響應,就啟動Service.

另一種方法是,將該Service獨立出來,運行在另一個進程中。(但是仔細想想,這個方法並不能避免Service被kill,因此不算正確答案)。

不知道其他方法還有什么?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM