android基礎篇(二),Service及IntentService,androidintent
一,概述上篇文章講到了四大組件之activity的生命週期,這篇文章將介紹與activity最相似的另外一個組件service以及它的一個子類intentService,service組件是android四大組件中與activity最為相似的組件了,它和activity最大的區別在於沒有介面,長期運行在後台,還有它的生命可以是四大組件中最長的一個了,沒有介面,生命週期持續長是service作為android開發中必不可可少的四大組件之一,也是選擇activity還是service的關鍵。要想學習service,我們首先得知道service的生命週期二,service的生命週期
service根據啟動方式的不一樣,走的生命週期也不一樣,下面我們看一張兩種方式啟動service的service的生命週期:
下面我們做個簡單的測試,觀察後台日誌的列印:
布局檔案
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_start" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="30dp" android:text="startService" /> <Button android:id="@+id/btn_end" android:layout_width="0dp" android:padding="30dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="stopService" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_bind" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="30dp" android:text="bindService" /> <Button android:id="@+id/btn_unbind" android:layout_width="0dp" android:padding="30dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="unbindService" /> </LinearLayout></LinearLayout>
CommonService.java
package com.example.servicedemo;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class CommonService extends Service { @Override public IBinder onBind(Intent arg0) { Log.e("onBind", "===============onBind================"); return null; } @Override public void onCreate() { Log.e("onCreate", "===============onCreate================"); super.onCreate(); } @Override public void onDestroy() { Log.e("onDestroy", "===============onDestroy================"); super.onDestroy(); } @Override public void onRebind(Intent intent) { Log.e("onRebind", "===============onRebind================"); super.onRebind(intent); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e("onStartCommand", "===============onStartCommand================"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.e("onUnbind", "===============onUnbind================"); return super.onUnbind(intent); }}
MainActivity.java
package com.example.servicedemo;import android.app.Activity;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends Activity implements View.OnClickListener{ private ServiceConnection conn = new ServiceConnection() { /** * 當前用戶端與服務中斷連線的時候回調,在這裡用戶端就是MainActivity * @param name */ @Override public void onServiceDisconnected(ComponentName name) { Log.e("onServiceDisconnected", "=======中斷連線========"); } /** * 當用戶端與Service串連成功的時候回調,在這裡用戶端就是MainActivity * @param name * @param service */ @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("onServiceConnected", "=======串連成功========"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_start = (Button) findViewById(R.id.btn_start); btn_start.setOnClickListener(this); Button btn_bind = (Button) findViewById(R.id.btn_bind); btn_bind.setOnClickListener(this); Button btn_end = (Button) findViewById(R.id.btn_end); btn_end.setOnClickListener(this); Button btn_unbind = (Button) findViewById(R.id.btn_unbind); btn_unbind.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent; switch (v.getId()) { case R.id.btn_start: intent = new Intent(this,CommonService.class); startService(intent); break; case R.id.btn_bind: intent = new Intent(this,CommonService.class); bindService(intent, conn, Service.BIND_AUTO_CREATE); break; case R.id.btn_end: intent = new Intent(this,CommonService.class); stopService(intent); break; case R.id.btn_unbind: unbindService(conn); break; } }}
service的啟動和activity類似,別忘了在資訊清單檔中配置service
<service android:name="com.example.servicedemo.CommonService"></service>
startService和stopService:
連續點5次startService按鈕,我們看到onCreate僅調用了一次,而onStartCommand方法每次都調用了:
從上面我們可以看出多次啟動一個已有的service只會調用一個onCreate,但每次都會調用onStartCommand方法。下面我們看看bindService和unbindService:
連點5次bindService按鈕:
我們看到,無論我們調用幾次bindService,onCreate和onBind只會調用一次
通過上面的圖片和測試我們對service的生命週期有了一定的認識,我們來總結一下service生命週期中各方法的調用
- onBind():該方法是Service子類必須實現的方法,該方法返回一個IBinder對象,應用程式可以通過該對象與Service組件通訊
- onCreate():當service第一次被建立的時候調用,注意是第一次被建立
- onDestroy():當service被銷毀的時候調用
- onStartCommand():每次用戶端調用startService()啟動該service的時候都會調用
- onUnbind:當該service上綁定的所有用戶端(通常是activity或broadcast)中斷連線的時候都將會回調該方法
關於service的使用和activity的使用類似,當我們程式不需要介面就可以實現我們的需求的時候或者我們需要在某個activity退出後要執行某些操作,這個時候我們得用service而不是activity了,下面我們看一看service的子類intentService。三,IntentService
IntentService是Service類的子類,用來處理非同步請求。用戶端可以通過startService(Intent)方法傳遞請求給IntentService。IntentService在onCreate()函數中通過HandlerThread單獨開啟一個線程來處理所有Intent請求對象(通過startService的方式發送過來的)所對應的任務,這樣以免交易處理阻塞主線程。執行完上一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,則自動停止Service;否則執行下一個Intent請求所對應的任務。
IntentService在處理事務時,還是採用的Handler方式,建立一個名叫ServiceHandler的內部Handler,並把它直接綁定到HandlerThread所對應的子線程。 ServiceHandler把處理一個intent所對應的事務都封裝到叫做onHandleIntent的虛函數;因此我們直接實現虛函數onHandleIntent,再在裡面根據Intent的不同進行不同的交易處理就可以了。
另外,IntentService預設實現了Onbind()方法,傳回值為null。
使用IntentService需要兩個步驟:
1、寫建構函式
2、實現虛函數onHandleIntent,並在裡面根據Intent的不同進行不同的交易處理就可以了。
好處:處理非同步請求的時候可以減少寫代碼的工作量,比較輕鬆地實現項目的需求
注意:IntentService的建構函式一定是參數為空白的建構函式(不然會報無空參數的構造方法初始化異常),然後再在其中調用super(“name”)這種形式的建構函式,那個name是寫給我們程式員看的,沒有什麼實際意義。我們只要給他一個字串就行了,通常我們會把它的名字作為參數傳進去
根據上面的描述,我們可以知道在該service中我們可以處理耗時操作,我們只要把我們要處理的操作放到onHandleIntent方法裡面處理。IntentService使用好方便,其他的和普通的service一樣。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。