Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android_Service(1)基本用法

Android_Service(1)基本用法

編輯:關於Android編程

一、Service的種類

1.按運行地點分類:

 

類別 區別 優點 缺點 應用 本地服務
(Local) 該服務依附在主進程上 服務依附在主進程上而不是獨立的進程,這樣在一定程度上節約了資源,另外Local服務因為是在同一進程因此不需要IPC,也不需要AIDL。相應bindService會方便很多。 主進程被Kill後,服務便會終止。 非常常見的應用如:HTC的音樂播放服務,天天動聽音樂播放服務。 遠程服務(Remote) 該服務是獨立的進程 服務為獨立的進程,對應進程名格式為所在包名加上你指定的android:process字符串。由於是獨立的進程,因此在Activity所在進程被Kill的時候,該服務依然在運行,不受其他進程影響,有利於為多個進程提供服務具有較高的靈活性。 該服務是獨立的進程,會占用一定資源,並且使用AIDL進行IPC稍微麻煩一點。 一些提供系統服務的Service,這種Service是常駐的。按運行類型分類:

 

2.按運行類型分類:

 

類別 區別 應用 前台服務 會在通知一欄顯示 ONGOING 的 Notification, 當服務被終止的時候,通知一欄的 Notification 也會消失,這樣對於用戶有一定的通知作用。常見的如音樂播放服務。 後台服務 默認的服務即為後台服務,即不會在通知一欄顯示ONGOING 的Notification。

當服務被終止的時候,用戶是看不到效果的。某些不需要運行或終止提示的服務,如天氣更新,日期同步,郵件同步等。

3.按運行方式分類:

 

 

類別 區別 startService 啟動的服務 主要用於啟動一個服務執行後台任務,不進行通信。停止服務使用stopService bindService 啟動的服務 該方法啟動的服務要進行通信。停止服務使用unbindService startService同時也 bindService 啟動的服務 停止服務應同時使用stepService與unbindService

 

二、Service的生命周期

\

三、通過Demo來了解服務的三種啟動方式和它們的生命周期

首先來看下代碼,主要是主界面類MainActivity,有四個Button,分別是兩種啟動服務的方式和兩種停止服務的方法,onCreate方法中Log打印出所在線程的ID,是為了比較與服務的線程是否相同。其中說下BindService代碼的邏輯,MainActivity類中創建了一個ServiceConnection的匿名類,在裡面重寫了onServiceConnected()方法和onServiceDisconnected()方法,這兩個方法分別會在Activity與Service建立關聯和解除關聯的時候調用。在onServiceConnected()方法中,我們又通過向下轉型得到了MyBinder的實例,有了這個實例,我們就建立了Activity和Service之間的聯系和信息的傳遞,然後就可以在Acrivity中調用服務中MyBinder中的方法了。最後是通過bindService()來啟動和建立聯系的,其中bindService方法中第三個參數是一個標志位,這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service,這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行。
如果想解除service和Activity的聯系,調用一下unbindService()方法就可以了。

 

package com.liangdianshui.service1;

import com.liangdianshui.R;
import com.liangdianshui.service1.MyService1.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.os.Process;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener {

	private final static String TAG = MainActivity.class.getSimpleName();

	private Button mBtStartService;
	private Button mBtStopService;
	private Button mBtBindService;
	private Button mBtUnbindService;

	private MyService1.MyBinder mBinder;

	private ServiceConnection mConnection = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			mBinder = (MyBinder) service;
			mBinder.toDo();
		}
	};

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

		initView();

		Log.i(TAG, "MainActivity thread ID:" + Thread.currentThread().getId());
	}

	private void initView() {
		// TODO Auto-generated method stub
		mBtStartService = (Button) findViewById(R.id.bt_start_server);
		mBtStopService = (Button) findViewById(R.id.bt_stop_server);
		mBtBindService = (Button) findViewById(R.id.bt_bind_server);
		mBtUnbindService = (Button) findViewById(R.id.bt_unbind_server);
		mBtStartService.setOnClickListener(this);
		mBtStopService.setOnClickListener(this);
		mBtBindService.setOnClickListener(this);
		mBtUnbindService.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		Intent intent = new Intent(MainActivity.this, MyService1.class);
		switch (v.getId()) {
		case R.id.bt_start_server:
			startService(intent);
			break;
		case R.id.bt_stop_server:
			stopService(intent);
			break;
		case R.id.bt_bind_server:
			bindService(intent, mConnection, BIND_AUTO_CREATE);
			break;
		case R.id.bt_unbind_server:
			unbindService(mConnection);
			break;
		}
	}

}
然後是MyService1類

 

package com.liangdianshui.service1;

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

public class MyService1 extends Service {

	private static final String TAG = MyService1.class.getSimpleName();

	private MyBinder mBinder = new MyBinder();

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mBinder;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		Log.i(TAG, "onCreate");
		Log.i(TAG, "MyService1 thread ID:" + Thread.currentThread().getId());
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.i(TAG, "onDestroy");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	class MyBinder extends Binder {

		public void toDo() {
			Log.i(TAG, "toDo");
		}
	}

}
最後記得在配置文件中聲明service類

 

 

 

我們點擊多下StartServer和一下StopServer看下運行效果:

\

仔細觀察,可以看到,當啟動一個Service的時候,會調用該Service中的onCreate()和onStartCommand()方法。如果再點擊一次StartServer按鈕,只看到日志中打印只看到日志中打印這次只有onStartCommand,沒有打印onCreate,證明了只有onStartCommand()方法執行了,onCreate()沒有執行,可是我們去管理程序應用那裡看下,服務還是在運行的,,然後點擊一下StopServer按鈕就可以將MyService停止了。

繼續,我們點擊多下BindServer和一下unBindServer看下運行效果:

\

根據效果圖可以看出,用Context.bindService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onBind()方法。這個時候調用者和服務綁定在一起,調用者退出了,系統就會先調用服務的onUnbind()方法,接著調用onDestroy()方法。如果調用bindService()方法前服務已經被綁定,多次調用bindService()方法並不會導致多次創建服務及綁定(也就是說onCreate()和onBind()方法並不會被多次調用)。如果調用者希望與正在綁定的服務解除綁定,可以調用unbindService()方法,調用該方法也會導致系統調用服務的onUnbind()-->onDestroy()方法。

最後,我們來一波混合點,先Bindserver然後點多次StartServer,然後點UnbindServer,最後點StopServer!你會發現,你點UnbindServer的時候並沒有打印出onDestory的Log出來,說明了服務沒有被銷毀,只有再點StopServer的時候,服務才銷毀了!因此不管你是單獨點擊Stop Service按鈕還是Unbind Service按鈕,Service都不會被銷毀,必要將兩個按鈕都點擊一下,Service才會被銷毀。也就是說,點擊Stop Service按鈕只會讓Service停止,點擊Unbind Service按鈕只會讓Service和Activity解除關聯,一個Service必須要在既沒有和任何Activity關聯又處理停止狀態的時候才會被銷毀。來看下效果圖:

\

 

現在我們來探究下Service和Thread的關系?為什麼要探究他們的關系呢?因為我們覺得這兩個東西很像,都是在後台運行的?那到底是不是呢?細心的會發現,之前那些效果圖可以看出,都有打印主界面和服務的線程ID出來,你會發現他們的線程ID是一樣的!

那好,我們重新運行項目,並點StartServer的按鈕,我們會看到:

\

可以看到,它們的線程id完全是一樣的,由此證實了Service確實是運行在主線程裡的,也就是說如果你在Service裡編寫了非常耗時的代碼,程序必定會出現ANR的。因此,如果想在服務中做耗時的操作,你可以在服務中開啟一個子線程,去運行耗時的操作!那為什麼要在服務進行耗時的操作呢!主要的原因是Service運行是完全不依賴UI的。即使Activity被銷毀,或者程序被關閉,只要進程還在,Service就可以繼續運行,可以一直在後台進行操作,那bindservice呢?bingservice啟動後,在Binder中進行耗時的操作,當Activity銷毀的時候,Binder停止工作,當Activity和service重新建立聯系的時候,能夠獲取到原有的Service中Binder的實例,繼續進行工作!所以,使用Service來處理後台任務,Activity就可以放心地finish,完全不需要擔心無法對後台任務進行控制的情況。

最後我們來總結一下:
1.Service的生命周期
(1)被啟動的服務的生命周期:如果一個Service被某個Activity 調用 Context.startService 方法啟動,那麼不管是否有Activity使用bindService綁定或unbindService解除綁定到該Service,該Service都在後台運行。如果一個Service被startService 方法多次啟動,那麼onCreate方法只會調用一次,onStart將會被調用多次(對應調用startService的次數),並且系統只會創建Service的一個實例(因此你應該知道只需要一次stopService調用)。該Service將會一直在後台運行,而不管對應程序的Activity是否在運行,直到被調用stopService,或自身的stopSelf方法。當然如果系統資源不足,android系統也可能結束服務。
(2)被綁定的服務的生命周期:如果一個Service被某個Activity 調用 Context.bindService 方法綁定啟動,不管調用 bindService 調用幾次,onCreate方法都只會調用一次,同時onStart方法始終不會被調用。當連接建立之後,Service將會一直運行,除非調用Context.unbindService 斷開連接或者之前調用bindService 的 Context 不存在了(如Activity被finish的時候),系統將會自動停止Service,對應onDestroy將被調用。
其中這裡要注意兩點:調用 bindService 綁定到Service的時候,你就應當保證在某處調用 unbindService 解除綁定(盡管 Activity 被 finish 的時候綁定會自動解除,並且Service會自動停止)
當在旋轉手機屏幕的時候,當手機屏幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉的話,旋轉其實是 Activity 的重新創建,因此旋轉之前的使用 bindService 建立的連接便會斷開(Context 不存在了)
(3)被啟動又被綁定的服務的生命周期:如果一個Service又被啟動又被綁定,則該Service將會一直在後台運行。並且不管如何調用,onCreate始終只會調用一次,對應startService調用多少次,Service的onStart便會調用多少次。調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。
(4)當服務被停止時清除服務:當一個Service被終止(1、調用stopService;2、不再有綁定的連接(沒有被啟動))時,onDestroy方法將會被調用,在這裡你應當做一些清除工作,比如停止在Service中創建並運行的線程。
2.Service 與 Thread 的關系和區別
(1)Service 與 Thread 的沒有任何關系

 

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