Activity 怎麼和 Service 綁定,怎麼在 Activity 中啟動自 己對應的 Service?
Activity 通過 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 進行綁定,當綁定成功的時候 Service 會將代理對象通過回調 的形式傳給 conn,這樣我們就拿到了 Service 提供的服務代理對象。
在 Activity 中可以通過 startService 和 bindService 方法啟動 Service。一 般情況下如果想擷取 Service 的服務物件那麼肯定需要通過 bindService()方 法,比如音樂播放器,第三方支付等。如果僅僅只是為了開啟一個背景工作那麼 可以使用 startService()方法。
Service 的生命週期
Service 有繫結模式和非繫結模式,以及這兩種模式的混合使用方式。不同 的使用方法生命週期方法也不同。
非繫結模式:當第一次調用 startService 的時候執行的方法依次為 onCreate()、onStartCommand(),當 Service 關閉的時候調用 onDestory 方 法。
繫結模式:第一次 bindService()的時候,執行的方法為 onCreate()、 onBind()解除綁定的時候會執行 onUnbind()、onDestory()。
上面的兩種生命週期是在相對單純的模式下的情形。我們在開發的過程中還 必須注意 Service 執行個體只會有一個,也就是說如果當前要啟動的 Service 已經存 在了那麼就不會再次建立該 Service 當然也不會調用 onCreate()方法。
一個 Service 可以被多個客戶進行綁定,只有所有的綁定對象都執行了
onBind()方法後該 Service 才會銷毀,不過如果有一個客戶執行了 onStart() 方法,那麼這個時候如果所有的 bind 客戶都執行了 unBind()該 Service 也不會 銷毀。
Service 的生命週期圖如下所示,協助大家記憶。
什麼是 IntentService?有何優點?
我們通常只會使用 Service,可能 IntentService 對大部分同學來說都是第 一次聽說。那麼看了下面的介紹相信你就不再陌生了。如果你還是不瞭解那麼在 面試的時候你就坦誠說沒用過或者不瞭解等。並不是所有的問題都需要回答上來的。
一、IntentService 簡介
IntentService 是 Service 的子類,比普通的 Service 增加了額外的功能。
先看 Service 本身存在兩個問題:
Service 不會專門啟動一條單獨的進程,Service 與它所在應用位於同一個進
程中;
Service 也不是專門一條新線程,因此不應該在 Service 中直接處理耗時的
任務;
二、IntentService 特徵
會建立獨立的 worker 線程來處理所有的 Intent 請求;
會建立獨立的 worker 線程來處理 onHandleIntent()方法實現的代碼,無需
處理多線程問題;
所有請求處理完成後,IntentService 會自動停止,無需調用 stopSelf()方法
停止 Service;
為 Service 的 onBind()提供預設實現,返回 null;
為 Service 的 onStartCommand 提供預設實現,將請求 Intent 添加到隊列
中;
使用 IntentService
本人寫了一個 IntentService 的使用例子供參考。該例子中一個
MainActivity 一個 MyIntentService,這兩個類都是四大組件當然需要在清單 檔案中註冊。這裡只給出核心代碼:
MainActivity.java:public void click(View view){Intent intent = new Intent(this, MyIntentService.class); intent.putExtra("start", "MyIntentService"); startService(intent);}MyIntentService.javapublic class MyIntentService extends IntentService { private String ex = "";private Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) { Toast.makeText(MyIntentService.this, "-e " + ex,Toast.LENGTH_LONG).show(); }};public MyIntentService(){ super("MyIntentService");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { ex = intent.getStringExtra("start");return super.onStartCommand(intent, flags, startId);}@Overrideprotected void onHandleIntent(Intent intent) { /*** 類比執行耗時任務* 該方法是在子線程中執行的,因此需要用到 handler 跟主線程進行通訊 */try { Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace();} mHandler.sendEmptyMessage(0); try {Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace(); }} }
Activity、Intent、Service 是什麼關係
他們都是 Android 開發中使用頻率最高的類。其中 Activity 和 Service 都是 Android 四大組件之一。他倆都是 Context 類的子類 ContextWrapper 的子類, 因此他倆可以算是兄弟關係吧。不過兄弟倆各有各自的本領,Activity 負責使用者 介面的顯示和互動,Service 負責背景工作的處理。Activity 和 Service 之間可 以通過 Intent 傳遞資料,因此可以把 Intent 看作是通訊使者。
Service 和 Activity 在同一個線程嗎?
對於同一 app 來說預設情況下是在同一個線程中的,main Thread (UI Thread)。
Service 裡面可以彈多士麼
可以的。彈多士有個條件就是得有一個 Context 上下文,而 Service 本身就是 Context 的子類,因此在 Service 裡面彈多士是完全可以的。比如我們在 Service 中完成下載任務後可以彈一個多士通知使用者。
什麼是 Service 以及描述下它的生命週期。Service 有哪 些啟動方法,有什麼區別,怎樣停用 Service?
在 Service 的生命週期中,被回調的方法比 Activity 少一些,只有 onCreate, onStart, onDestroy,
onBind 和 onUnbind。
通常有兩種方式啟動一個 Service,他們對 Service 生命週期的影響是不一樣的。
- 通過 startService
Service 會經曆 onCreate 到 onStart,然後處於運行狀態,stopService
的時候調用 onDestroy 方法。
如果是調用者自己直接退出而沒有調用 stopService 的話,Service 會一直
在後台運行。
- 通過 bindService
Service 會運行 onCreate,然後是調用 onBind,這個時候調用者和 Service 綁定在一起。調用者退出了,Srevice 就會調用 onUnbind->onDestroyed 方 法。
所謂綁定在一起就共存亡了。調用者也可以通過調用 unbindService 方法來 停止服務,這時候 Srevice 就會調用 onUnbind->onDestroyed 方法。 需要注意的是如果這幾個方法交織在一起的話,會出現什麼情況呢? 一個原則是 Service 的 onCreate 的方法只會被調用一次,就是你無論多少次的 startService 又 bindService,Service 只被建立一次。
如果先是 bind 了,那麼 start 的時候就直接運行 Service 的 onStart 方法,如 果先是 start,那麼 bind 的時候就直接運行 onBind 方法。
如果 service 運行期間調用了 bindService,這時候再調用 stopService 的話,service 是不會調用 onDestroy 方法的,service 就 stop 不掉了,只能調用 UnbindService, service 就會被銷毀
如果一個 service 通過 startService 被 start 之後,多次調用 startService 的 話,service 會多次調用 onStart 方法。多次調用 stopService 的話,service 只會調用一次 onDestroyed 方法。
如果一個 service 通過 bindService 被 start 之後,多次調用 bindService 的話, service 只會調用一次 onBind 方法。
多次調用 unbindService 的話會拋出異常。
在 service 的生命週期方法 onstartConmand()可不可以執行網路操作?如何在 service 中執行網路操作?
可以直接在 Service 中執行網路操作,在 onStartCommand()方法中可以執行網路操作
如何提高service的優先順序?
Android 系統對於記憶體管理有自己的一套方法,為了保障系統有序穩定的運信,
系統內部會自動分配,控製程序的記憶體使用量。當系統覺得當前的資源非常有限的時候,
為了保 證一些優先順序高的程式能運行,就會殺掉一些他認為不重要的程式或者服務來釋放記憶體。
這樣就能保證真正對使用者有用的程式仍然再運行。如果你的 Service 碰上了這種情況,多半會先被殺掉。
但如果你增加 Service 的優先順序就能讓他多留一會,
我們可以用 setForeground(true) 來設定 Service 的優先順序。
為什麼是 foreground ? 預設啟動的 Service 是被標記為 background,當前啟動並執行 Activity
一般被標記為 foreground,也就是說你給 Service 設定了 foreground 那麼他就和正在啟動並執行
Activity 類似優先順序得到了一定的提高。當讓這並不能保證你得 Service
永遠不被殺掉,只是提高了他的優先順序。
service 如何定時執行?
當啟動service進行背景工作的時候,我們一般的 做法是啟動一個線程,然後通過sleep方法來控制進行定時的任務,如輪詢操作,訊息推送。這樣容易被系統回收。
service被回收是我們不能控制的,但是我們可以控制service的重啟活動。在service的onStartCommand
方法中可以返回一個參數來控制重啟活動
使用AlarmManager,根據AlarmManager的工作原理,alarmmanager會定時的發出一條廣播,然後在自己的項目裡面註冊這個廣播,重寫onReceive方法,在這個方法裡面啟動一個service,然後在service裡面進行網路的訪問操作,當擷取到新訊息的時候進行推送,同時再設定一個alarmmanager進行下一次的輪詢,當本次輪詢結束的時候可以stopself結束改service。這樣即使這一次的輪詢失敗了,也不會影響到下一次的輪詢。這樣就能保證推送任務不會中斷
Service 的 onStartCommand 方法有幾種傳回值?各代表什麼意思?
有四種傳回值,不同值代表的意思如下:
START_STICKY:如果 service 進程被 kill 掉,保留 service 的狀態為開始狀態,但不保留遞送的 intent 對象。隨 後系統會嘗試重新建立 service,由於服務狀態為開始狀態,所以建立服務後一定會調用 onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到 service,那麼參數 Intent 將為 null。
START_NOT_STICKY:“非粘性的”。使用這個傳回值時,如果在執行完 onStartCommand 後,服務被異常 kill 掉,系統不會自動重啟該服務。
START_REDELIVER_INTENT:重傳 Intent。使用這個傳回值時,如果在執行完 onStartCommand 後,服務被異 常 kill 掉,系統會自動重啟該服務,並將 Intent 的值傳入。
**START_STICKY_COMPATIBILITY:**START_STICKY 的相容版本,但不保證服務被 kill 後一定能重啟。
Service 的 onRebind(Intent)方法在什麼情況下會執行?
如果在 onUnbind()方法返回 true 的情況下會執行,否則不執行。
Activity 調用 Service 中的方法都有哪些方式?
Binder:
通過 Binder 介面的形式實現,當 Activity 綁定 Service 成功的時候 Activity 會在 ServiceConnection 的類 的 onServiceConnected()回調方法中擷取到 Service 的 onBind()方法 return 過來的 Binder 的子類,然後通過對象調用方法。
Aidl:
aidl 比較適合當用戶端和服務端不在同一個應用下的情境。
Messenger:
它引用了一個Handler對象,以便others能夠向它發送訊息(使用mMessenger.send(Message msg)方法)。該類允許跨進程間基於Message的通訊(即兩個進程間可以通過Message進行通訊),在服務端使用Handler建立一個Messenger,用戶端持有這個Messenger就可以與服務端通訊了。一個Messeger不能同時雙向發送,兩個就就能雙向發送了