一、Service初步瞭解
Service是Android中四大組件之一,用來進行後臺處理時間長的任務操作,可以避免Android的ANR。最爲經典的使用場景是在音樂播放器中,使用Service可以使音樂在後臺播放,即使我們離開播放器APP音樂也不會停止。Service+Notification+Broadcast Receive三者聯合使用將會得到意想不到的用戶體驗。作爲組件,Service需要在Manifirst.xml文件中進行註冊。
想要使用Service服務必須繼承android.app.Service類,主要處理其中的以下方法:
public class MyStartService extends Service {
public void onCreate() {
super.onCreate();
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent intent) {
return null;
}
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
public void onDestroy() {
super.onDestroy();
}
}
二、Service的兩種啓動方式
1、startService():Context組件通過調用此方法可以啓動一個Service,此時啓動的服務不收Context組件的生命週期的影響。也就是說當啓動服務的組件銷燬後,服務依然存在。此時Service的生命週期相關的函數是onCreat()、onStart()、onStartCommand()、onDestory();
startService()開始服務:
stopService()停止服務:
當我們多次startService()時,onCreate()只會調用一次,而onStart()和onStartCommand()可以多次調用,不管調用多少次startService(),我們只需要使用一次stopService()就可以將服務銷燬,以下是我們進行3次啓動1次銷燬的log日誌:
2、bindService():Context組件通過調用此方法可以綁定一個Service,當啓動它的組件銷燬時,其綁定的服務也會一起銷燬,有種愛叫做不求同生,但願同死的趕腳。在啓動組件銷燬前,我們必須要保證它與綁定的服務間要有解綁動作,不然Android系統會報錯誤。在進行綁定時會涉及到一個ServiceConnection類,當綁定成功時會回調其中的onServiceConnected()方法。
在進行綁定服務的時候相關的生命週期方法是:onCreate()、onBind()、onUnbind()、onDestory();
bindService()綁定服務:
unBindService()解除綁定:
多次調用bindService()綁定服務時,不會重複調用生命週期函,一下是3次綁定1次解除綁定的log:
三、同時使用兩種方式來啓動Service服務
當我們同時使用了startService()開始服務和bindService()綁定服務時,必須調用一次stopService()和unBindService()才能夠銷燬一個服務。大家跟着我的操作來一起看看log日誌:
操作步驟:
1、startService()開始服務
2、bindService()綁定服務
3、startService()開始服務
4、bindService()綁定服務
5、stopService()服務
6、startService()開始服務
7、startService()開始服務
8、stopService()服務
9、unBindService()服務
源代碼部分:
Activity代碼:
public class SjcServiceActivity extends Activity {
Intent startServiceIntent;
ServiceConnection connection;
boolean isBindService = false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
startServiceIntent = new Intent(this, MyStartService.class);
connection = new ServiceConnection() {
//當綁定的服務崩潰或被殺死導致的連接中斷時被調用,自己解除綁定時則不會被調用
public void onServiceDisconnected(ComponentName name) {
Log.i("TAG", "MyStartService --> onServiceDisconnected");
unBindServie();
}
//當綁定服務時會調用這個方法
public void onServiceConnected(ComponentName name, IBinder service) {
isBindService = true;
Log.i("TAG", "MyStartService --> onServiceConnected");
}
};
}
protected void onDestroy() {
super.onDestroy();
unBindServie();//當Activity銷燬時,必須解除所綁定的服務,不然會報錯
}
public void onClick(View v) {
Button btn = (Button)v;
switch (v.getId()) {
case R.id.btn_startService:
startService(startServiceIntent);
break;
case R.id.btn_stopService:
stopService(startServiceIntent);
break;
case R.id.btn_bindService:
bindService(startServiceIntent, connection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_unbindService:
unBindServie();
break;
default:
Toast.makeText(this, btn.getText(), Toast.LENGTH_SHORT).show();
break;
}
}
private void unBindServie() {
if(isBindService) {
isBindService = false;
unbindService(connection);
}
}
}
Activity的佈局xml文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Service"
android:id="@+id/btn_startService"
android:layout_margin="5dp"
android:onClick="onClick"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Service"
android:id="@+id/btn_stopService"
android:layout_margin="5dp"
android:onClick="onClick"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bind Service"
android:id="@+id/btn_bindService"
android:layout_margin="5dp"
android:onClick="onClick"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Unbind Service"
android:id="@+id/btn_unbindService"
android:layout_margin="5dp"
android:onClick="onClick"
/>
</LinearLayout>
</FrameLayout>
Service代碼:
public class MyStartService extends Service {
public void onCreate() {
super.onCreate();
Log.i("TAG", "MyStartService --> onCreate");
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("TAG", "MyStartService --> onStart");
}
//在Android2.0時系統引進了onStartCommand方法取代onStart方法,
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("TAG", "MyStartService --> onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//服務在綁定時調用,
//如果返回值爲null,則不會調用ServiceConnection的onServiceConnected()方法
public IBinder onBind(Intent intent) {
Log.i("TAG", "MyStartService --> onBind");
return new Binder() {
};
}
public boolean onUnbind(Intent intent) {
Log.i("TAG", "MyStartService --> onUnbind");
return super.onUnbind(intent);
}
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "service destroy", Toast.LENGTH_SHORT).show();
Log.i("TAG", "MyStartService --> onDestroy");
}
}
Service在清單文件中的註冊:
<service android:name="com.sjc.myproject.apis.service.MyStartService"></service>