我們在Service(Ⅰ)中瞭解了Service最基本的知識點,今天我們繼續學習Service這個組件(神器)。 先來說一下Service的生命周期:跟Activity相比,Service的生命周期就太簡單了:onCreate()->onStart()->onDestroy() 【主題】:Activ ...
我們在Service(Ⅰ)中瞭解了Service最基本的知識點,今天我們繼續學習Service這個組件(神器)。
先來說一下Service的生命周期:跟Activity相比,Service的生命周期就太簡單了:onCreate()->onStart()->onDestroy()
----------------------------------------------------------------------------------------------------------------------------------------
【主題】:Activity與Service之間的Communication
【問題】:由上貼我們知道,當我們點擊START SERVICE按鈕後,服務的onCreate()和onStartCommand()方法會得到執行,此後Service是一直存在於後臺運行的,Activity無法控制Service中具體的邏輯運行,那麼這樣Activity只相當於起到一個通知的作用,除了告訴Service你可以開始工作了。那麼這樣顯然會分離兩者之間的關聯性,這也不是我們需要的結果!
【後果】:如果出現以上的問題,那麼在我們平時的項目開發過程中(拿小編做手機開發項目而言),一直存在的Service很有可能會引起功耗的問題,這將嚴重影響手機的運行效率!
【要求】:我們能否將Activity與Service建立一種聯繫,當Activity終結之時,Service也銷毀,也就是有沒有辦法讓Activity和Service能夠“不求同生,但求共死”?
答案是肯定的!這就涉及到Service的另一個重要知識點:綁定與解綁!
直接代碼走起,看過來:
(1)MyService.java
public class MyService extends Service{
private static final String TAG = "MyService";
private DownloadBinder mBinder = new DownloadBinder(); // 定義一個DownloadBinder類
class DownloadBinder extends Binder { // 讓DownloadBinder成為Binder的子類 public void startDownload() { // 定義開始下載的方法 Log.d(TAG, "startDownload executed"); } public int getProgress() { // 定義一個查看下載進度的方法 Log.d(TAG, "getProgress executed"); return 0; } } @Nullable @Override public IBinder onBind(Intent intent) { // onBind()方法,這個方法將在綁定後調用 return mBinder; // 返回IBinder的實例 --> DownloadBinder類的實例 } ... // 這邊就是之前定義好的onStart()、onStartCommand()、onDestroy()三個方法 }
(2)接下來,我們在Layout中添加兩個按鈕 BIND SERVICE 和 UNBIND SERVICE:
(3)MainActivity.java
public class MainActivity extends Activity implements View.OnClickListener{
private ServiceConnection connection = new ServiceConnection() { // 創建一個ServiceConnection的匿名內部類 @Override public void onServiceConnected(ComponentName name, IBinder service) { // 重寫onServiceConnected()方法 MyService.DownloadBinder downloadBinder = (MyService.DownloadBinder) service; // 向下轉型取得downloadBinder實例 downloadBinder.startDownload(); // 在Activity中調用Service的方法 downloadBinder.getProgress(); // 在Activity中調用Service的方法 }
@Override public void onServiceDisconnected(ComponentName name) { // 重寫onServiceDisconnected()方法 } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button startService = (Button) super.findViewById(R.id.start_service); Button stopService = (Button) super.findViewById(R.id.stop_service); Button bindService = (Button) super.findViewById(R.id.bind_service); Button unbindService = (Button) super.findViewById(R.id.unbind_service); // 不解釋!!! startService.setOnClickListener(this); stopService.setOnClickListener(this); bindService.setOnClickListener(this); unbindService.setOnClickListener(this); }
@Override public void onClick(View v) { switch (v.getId()) { case R.id.start_service: Intent startIntent = new Intent(this, MyService.class); // START 服務 --> onCreate() --> onStartCommand() startService(startIntent); break; case R.id.stop_service: Intent stopIntent = new Intent(this, MyService.class); // STOP 服務 --> onDestroy() stopService(stopIntent); break; case R.id.bind_service: // 綁定 --> ? Intent bindIntent = new Intent(this, MyService.class); bindService(bindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: // 解綁 --> ? unbindService(connection); break; default: break; } } }
(4)我們一起來看一下bindService(bindIntent, connection, BIND_AUTO_CREATE)這個方法:
bindService接收了3個參數:
bindIntent:這個參數傳入的就是我們的intent,目的就是調用MyService這個服務。
connection:這個參數傳入的就是創建好的ServiceConnection的實例,這個參數代表著我們的Activity是要和Service綁定在一起的!
BIND_AUTO_CREATE:這是一個FLAG,表示在活動和服務進行綁定後自動創建服務。註意!註意!是自動創建服務,也就是說MyService會執行onCreate()方法,但是不會執行onStartCommand()方法!
(5)好了,說到這邊,我們直接來看看代碼最終的效果吧:
小編通過排列組合,對按鈕進行了狂烈的點擊,跟大家一起分享一下上圖中Log的情況,分3種情況:
(1)START SERVICE + STOP SERVICE:
當我們先點擊START SERVICE:此時服務啟動,調用onCreat()和onStartCommand()方法;
當我們後點擊STOP SERVICE:此時,服務被銷毀,調用onDestroy()方法。
(2)BIND SERVICE + UNBIND SERVICE:
當我們先點擊BIND SERVICE:此時服務僅僅是創建,並未啟動!所以調用的只是onCreate()方法。此時Activity與Service綁定,會同時調用onBind()方法,此時onServiceConnected()方法會被執行,還記的onBind()方法的返回類型不?我們通過Log可以很明顯發現,Activity調用了服務內部的兩個自定義方法。
當我們後點擊UNBIND SERVICE:由於服務還未啟動,而BIND SERVICE只是將服務創建好並與活動進行綁定,那麼解綁後,勢必會銷毀這個Service,所以onDestroy()被執行!
(3)START SERVICE + BIND SERVICE + UNBIND SERVICE + STOP SERVICE:
這麼長的一串字元,小編看的都想吐~~~~
分析吧:
1、我們先點擊START SERVICE:onCreat()和onStartCommand()方法被執行,這個就不用多說了;
2、然後點擊UNBIND SERVICE:這個時候其實活動已經在後臺運行了,我們此時將活動和服務綁定,那麼onCreate()不會再執行,只會執行onServiceConnected()方法,Log裡面打出來看的很清楚。
3、此時你如果手賤,想STOP SERVICE:那麼恭喜你,毫無反應!為什麼?因為你都沒解綁,你怎麼銷毀?
4、OK,那我們先解綁,我們點擊UNBIND SERVICE:此時一個奇怪的現象發生了,LOG日誌沒有列印出Destroy()這個方法啊?沒有被執行啊!不是說bind了Service之後,unbind就會銷毀這個服務嗎?這跟我們第(2)條不符合啊。
5、好吧,我們來看看,其實原因很簡單:我們先start了Service,那麼此時服務已經在後臺運行了,這個時候你bind,讓Service和Activity綁定,其實是沒有什麼意義的。但是既然綁定了,你如果不解綁,那麼Destroy()毫無用武,所以,這種情況和(2)中分析的還是有區別的,此是解綁完後,服務還是舒舒服服的在後臺運行,所以,要想幹掉這個服務,你必須要STOP SERVICE。
我想你是不是要好好消化一下,很快就可以理解的!
6、放我們解綁後,再STOP SERVICE:這個時候Service就被槍斃了!
----------------------------------------------------------------------------------------------------------------------------------------
【後記】
可能小編編寫的帖子過於簡單,也過於基礎了,但是小編始終相信,掌握好基礎是相當重要的,再簡單的知識點也能看出大門道!希望各位Android大神不要嫌棄鄙視啊。
如果你喜歡,請幫我點個贊,或者可以留言我們一起交流學習,如果文章中有任何錯誤和解釋不到位的,請批評指正!謝謝啦~