編輯:關於Android編程
一、Service的種類
1.按運行地點分類:
類別 區別 優點 缺點 應用 本地服務
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 的沒有任何關系
本文實例講述了Android編程之TabWidget選項卡用法。分享給大家供大家參考,具體如下:1 概覽TabWidget與TabHost。tab組件一般包括TabHos
一、Object java.lang.Object 是所有類的根類,每個 Java 對象都是一個 Object。本文主要說明的是 Object 類中的一組方法,這些方法是
1、Pull概述Android系統中和創建XML相關的包為org.xmlpull.v1,在這個包中不僅提供了用於創建XML的 XmlSerializer,還提
起因寫博客就像講故事,得有起因,經過,結果,人物,地點和時間。今天就容我給大家講一個故事。人物呢,肯定是我了。故事則發生在最近的這兩天,地點在coder君上班的公司。那天