Android學習筆記---Service及IntentService理解
一.Android Service服務:
Android中的服務是運行在后台的服務,他是不可見的沒有界面的東西。你可以啟動一個服務Service來播放音樂,或者記錄你地理信息位置的改變,或者啟動一個服務來運行並一直監聽某種動作。Service和其他組件一樣,都是運行在主線程中,因此不能用它來做耗時的請求或者動作。你可以在服務中開一一個線程,在線程中做耗時動作。
服務的生命周期圖:
1.如何創建和開啟一個服務:
第一步:創建一個類 ExampleService.java 繼承android.app.Service
第二步:覆蓋其中繼承的方法 如下:
public class ExampleService extends Service { private static final String TAG = "Example"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "ExampleService===>>onCreate"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.i(TAG, "ExampleService===>>onStart"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ExampleService===>>onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "ExampleService===>>onDestroy"); super.onDestroy(); } }
第三步:啟動服務:
Intent intent = new Intent(MainActivity.this, ExampleService.class); startService(intent);
第四步:關閉服務:
stopService(intent);//關閉服務
服務運行的生命周期順序:
[onCreate()-->onStartCommand()--->onStart()-->運行服務--->調用stopService()--->onDestory()]
在Activity中通過startService()開啟的服務,開啟之后及時現在我們關閉Activity服務還一直在后台運行,只有調用stopService()才能關閉服務。
關閉Activity之后 我們在此點擊按鈕 重新開啟服務。
注意:服務在后台運行我們再次點擊startService()開啟服務。將不會在調用 onCreate()服務。一個服務只會創建一次,銷毀一次,但可以開始多次,因此,onCreate和onDestroy方法只會被調用一次,而onStart(或onStartCommand)方法會被調用多次。
如下圖:
點擊stopService()方法將關閉服務:
注意:onStart方法是在Android2.0之前的平台使用的.在2.0及其之后,則需重寫onStartCommand方法,同時,舊的onStart方法則不會再被調用.
二.bindService()
Bound service 允許其它的組件(比如Activities)綁定到這個Service上,可以發送請求,也可以接受請求,甚至進行進程間的通話。Bound service 僅僅在服務於其它組件時存在,不能獨自無限期的在后台運行。
調用者和服務綁在一起,調用者一旦退出服務也就終止[onCreate()-->onBind()-->onUnbind()-->onDestory()]
1.創建Bound Services
當創建一個能提供綁定功能的服務時,我們必須提供一個IBinder對象,客戶端能使用這個對象與服務進行交互。在Android中有三種方式定義方式:
1.擴展Binder類
2.使用Messenger
3.使用AIDL (Android Interface Definition Language)
創建 步驟:
第一步:.創建一個類BinderService.java 繼承 android.app.Service
public class BinderService extends Service { public class MyBinder extends Binder { public BinderService getBinderService() { return BinderService.this; } } private MyBinder binder=new MyBinder(); private static final String TAg = "BinderService"; @Override public IBinder onBind(Intent intent) { Log.i(TAg, "BinderService===>onBind()"); return binder; } public void UpFile() { Log.i(TAg, "BinderService===>UpFile()"); } @Override public void onCreate() { Log.i(TAg, "BinderService===>onCreate()"); super.onCreate(); } @Override public void onDestroy() { Log.i(TAg, "BinderService===>onDestroy()"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log.i(TAg, "BinderService===>onUnbind()"); return super.onUnbind(intent); } }
第二步:在Service類中,創建一個Binder實例 包含客戶端能調用的公共方法 返回當前服務對象
public class MyBinder extends Binder { public BinderService getBinderService() { return BinderService.this; } }
第三步:在onBind()方法中返回Binder實例
private MyBinder binder=new MyBinder(); private static final String TAg = "BinderService"; @Override public IBinder onBind(Intent intent) { return binder; }
第四步:在客戶端,從onServiceConnected()方法中獲得Binder實例。
private void bindService() { Intent intent=new Intent(MainActivity.this,BinderService.class); bindService(intent,conn,Context.BIND_AUTO_CREATE); } private void unBind() { if(isConnected) { unbindService(conn); } } private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { isConnected=false; } @Override//在onServiceConnected 中獲取Binder的實例 public void onServiceConnected(ComponentName name, IBinder binder) { MyBinder myBinder=(MyBinder)binder; BinderService service=myBinder.getBinderService(); service.UpFile(); isConnected=true; } };
通過調用 bindService()開啟服務 。
調用unBind()關閉服務,或者我們關閉Activity也會關閉服務
三.Android中Service運行在主線程中。
Android 中的服務是運行在主線程上的,通過下面的例子來說明Android服務運行的線程。如果是運行在主線程的,
那在服務中步要運行太耗時的操作。如果運行態耗時的操作將會是整個Activity處於假死狀態,無在進行別的操作。如何要運行耗時操作
要用到多線程Thread 或者異步操作 InentService.
創建一個 MyServiceThread.java 繼承 Service的服務:
public class MyServiceThread extends Service { private static final String TAG = "MyServiceThread"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "MyServiceThread===>>onCreatre===>>線程ID:"+Thread.currentThread().getId()); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { try {
//這里進行耗時的操作 Log.i(TAG, "MyServiceThread===>>onStartCommand===>>線程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下載。。。。。"); Thread.sleep(5000); Log.i(TAG, "文件下載完成。"); } catch (InterruptedException e) { e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "MyServiceThread===>>onDestroy===>>線程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }
程序為開啟耗時服務時:
開啟耗時服務時:
運行截圖:下圖可看出Android 中的Service確實是運行在主線程中。從運行前和運行后,當我們點擊開啟服務,按鈕在服務沒有運行
結束時,背景處於黃色,此時不能進行其他的操作。如果要運行耗時的操作需要應用多線程操作。
三.Android中Service多線程操作運行耗時操作。
一下演示Android服務如何在多線程下進行耗時操作。
1.創建ManyThreadService.java 服務
public class ManyThreadService extends Service { private static final String TAG = "ManyThreadService"; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { Log.i(TAG, "ManyThreadService==>>onCreate==>線程ID:"+Thread.currentThread().getId()); } private class MyThread extends Thread { @Override public void run() { try { Log.i(TAG, "ManyThreadService==>>文件下載線程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下載中。。。。。>>文件現在線程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件現在完成。 >>文件下線線程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ManyThreadService==>>onStartCommand中開啟線程==>線程ID"+Thread.currentThread().getId()); new MyThread().start(); return START_STICKY; } @Override public void onDestroy() { Log.i(TAG, "ManyThreadService==>>onDestory==>線程ID"+Thread.currentThread().getId()); super.onDestroy(); } }
2.創建新線程進行耗時操作:
private class MyThread extends Thread { @Override public void run() { try { Log.i(TAG, "ManyThreadService==>>文件下載線程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下載中。。。。。>>文件現在線程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件現在完成。 >>文件下線線程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.開啟新線程:
public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ManyThreadService==>>onStartCommand中開啟線程==>線程ID"+Thread.currentThread().getId()); new MyThread().start(); return START_STICKY; }
運行效果:從下圖看出出,多線程並行操作,提高執行的效率。如果要在Android服務中執行耗時的並行操作服務,適應多線程操作時不錯的選擇。
如果只是運行異步請求操作 IntentService是不錯的選擇。
三.Android中IntentSevice操作。
IntentService是Service類的子類,用來處理異步請求。客戶端通過startService(Intent)方法傳遞請求給IntentService,
IntentService通過worker thread處理每個Intent對象,執行完所有工作后自動停止Service。
寫構造方法 復寫onHandleIntent()方法
IntentService執行如下操作
1.創建一個與應用程序主線程分開worker thread用來處理所有通過傳遞過來的Intent請求
2.創建一個work queue,一次只傳遞一個intent到onHandleIntent()方法中,從而不用擔心多線程帶來的問題
3.當處理完所有請求后自動停止服務,而不需要我們自己調用stopSelf()方法
4.默認實現了onBind()方法,返回值為null
5. 默認實現了onStartCommand()方法,這個方法將會把我們的intent放到work queue中,然后在onHandleIntent()中執行。
創建 MyIntentService.java 繼承:android.app.IntentService
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService() { super("MyIntentService"); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "MyIntentService==>>onCreate==>>線程ID:"+Thread.currentThread().getId()); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "MyIntentService==>>onStartCommand==>>線程ID:"+Thread.currentThread().getId()); return super.onStartCommand(intent, flags, startId); } @Override protected void onHandleIntent(Intent intent) { try { Log.i(TAG, "MyIntentService==>>onHandleIntent==>>線程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下載中。。。。。>>文件下載線程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件現在完成>>文件下載線程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onDestroy() { Log.i(TAG, "MyIntentService==>>onDestory==>>線程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }
運行效果:從下圖可以看出,在每次開啟服務時傳過去的inent,耗時操作都是有一個線程來執行處理。而所有操作排列成一個線程隊列,先執行完個操作,緊接着
執行下一個操作。執行完所以操作后 服務會自動onDestory操作進行銷毀。
本寫的這里,有些問題是我通過實驗總結出來的,有錯誤的地方請指出來。錯誤的地方希望大家指出。謝謝。