Android 之Service使用攻略
Service無法自行啟動,訪問者啟動它的方式分為兩種,即startService(非繫結式)和bindService (繫結式),相關介紹如下:
* startService:即非繫結式。訪問者使用這種方式啟動service後,service將不受訪問者控制,也無法與訪問者進行資料通訊,它會無限地執行下去,必須呼叫stopSelf()方法或者其他元件(包括訪問者)呼叫stopService()方法來停止。它的生命週期:onCreate->onStartCommand()->……>onDestory(),其中,onCreate用於初始化工作,多次呼叫startService啟動同一個服務,onCreate方法只會被呼叫一次,onStartCommand會被呼叫多次,onDestory在銷燬時也只會被呼叫一次。
* bindService:即繫結式。訪問者使用這種方式啟動service後,被啟動的service受訪問者的控制,訪問者將通過一個IBinder介面的物件與被繫結的service進行通訊,並且可以通過unbindService()方法隨時關閉service。一個service可以同時被多個訪問者繫結,只有當多個訪問者都主動解除繫結關係之後,系統才會銷燬service。它的生命週期:onCreate->onBind->....>onUnbind->onDestory,其中,onBind用於返回一個通訊物件(IBinder)給訪問者,訪問者可以通過該IBinder物件呼叫service的相關方法。當多個訪問者繫結同一個service時,onCreate只會被呼叫一次,onBind、unOnbind方法會被呼叫與訪問者數目相關的次數,onDestory在銷燬時只會被呼叫一次。
startService和bindService,用哪個好?
開啟服務時,它們與activity之間的關係:
1、startService開啟服務以後,與activity就沒有關聯,不受影響,獨立執行。
2、bindService開啟服務以後,與activity存在關聯,退出activity時必須呼叫unbindService方法,否則會報ServiceConnection洩漏的錯誤。
因此,根據實際需求使用最好。
Service
類若呼叫startService啟動時,有個生命週期方法叫onStartCommand,
這個方法有一個整型的返回值:START_STICKY_COMPATIBILITY
START_STICKY
START_NOT_STICKY
START_REDELIVER_INTENT
預設情況下,當我們的服務因為系統記憶體吃緊或者其他原因被異常終止時,系統會嘗試在某個時刻重新啟動服務,
START_NOT_STICKY:服務不會重新建立,除非你再次呼叫startService
START_STICKY / START_STICKY_COMPATIBILITY:服務重新建立並啟動,依次回撥onCreate、onStartCommand,如果沒有新的intent傳給此service,onStartCommand
接受的將是一個空的intent
。
START_STICKY_COMPATIBILITY:START_STICKY的相容版本,2.0之下使用,它不保證一定呼叫onStartCommand
.
START_REDELIVER_INTENT:服務重新建立並啟動,依次回撥onCreate,onStartCommand,並且會把最後一次傳給此服務的intent
重新發給onStartCommand
。
PS:
1、系統預設是START_STICKY。另外,為app保活著想,也應該設為START_STICKY
2、如果一個service被startService啟動,然後其他元件再執行bindService繫結該service,service的onCreate不會再被回撥,而是直接回撥onBind方法;當該元件unBindService時,service的onUnbind方法被回撥,但是service不會被銷燬,直到自己呼叫stopSelf方法或者其他元件呼叫stopService方法時才會被銷燬。
1. Service分類
2.2 可通訊的服務Service
- 接下來將在Service的基礎用法上,增設“與Activity通訊”的功能,即使用繫結Service服務(Binder類、bindService()、onBind()、unbindService()、onUnbind())
- 步驟1:在新建子類繼承Service類,並新建一個子類繼承自Binder類、寫入與Activity關聯需要的方法、建立例項
public class MyService extends Service {
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
System.out.println("執行了onCreat()");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("執行了onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("執行了onDestory()");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
System.out.println("執行了onBind()");
//返回例項
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("執行了onUnbind()");
return super.onUnbind(intent);
}
//新建一個子類繼承自Binder類
class MyBinder extends Binder {
public void service_connect_Activity() {
System.out.println("Service關聯了Activity,並在Activity執行了Service的方法");
}
}
}
- 步驟2:在主佈局檔案再設定兩個Button分別用於繫結和解綁Service
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="scut.carson_ho.demo_service.MainActivity">
<Button
android:layout_centerInParent="true"
android:id="@+id/startService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="啟動服務" />
<Button
android:layout_centerInParent="true"
android:layout_below="@+id/startService"
android:id="@+id/stopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服務" />
<Button
android:layout_centerInParent="true"
android:layout_below="@id/stopService"
android:id="@+id/bindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="繫結服務" />
<Button
android:layout_centerInParent="true"
android:layout_below="@id/bindService"
android:id="@+id/unbindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解綁服務"
/>
</RelativeLayout>
- 步驟3:在Activity通過呼叫MyBinder類中的public方法來實現Activity與Service的聯絡
即實現了Activity指揮Service幹什麼Service就去幹什麼的功能
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.MyBinder myBinder;
//建立ServiceConnection的匿名類
private ServiceConnection connection = new ServiceConnection() {
//重寫onServiceConnected()方法和onServiceDisconnected()方法
//在Activity與Service建立關聯和解除關聯的時候呼叫
@Override
public void onServiceDisconnected(ComponentName name) {
}
//在Activity與Service解除關聯的時候呼叫
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//例項化Service的內部類myBinder
//通過向下轉型得到了MyBinder的例項
myBinder = (MyService.MyBinder) service;
//在Activity呼叫Service類的方法
myBinder.service_connect_Activity();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService = (Button) findViewById(R.id.startService);
stopService = (Button) findViewById(R.id.stopService);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService = (Button) findViewById(R.id.bindService);
unbindService = (Button) findViewById(R.id.unbindService);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//點選啟動Service
case R.id.startService:
//構建啟動服務的Intent物件
Intent startIntent = new Intent(this, MyService.class);
//呼叫startService()方法-傳入Intent物件,以此啟動服務
startService(startIntent);
break;
//點選停止Service
case R.id.stopService:
//構建停止服務的Intent物件
Intent stopIntent = new Intent(this, MyService.class);
//呼叫stopService()方法-傳入Intent物件,以此停止服務
stopService(stopIntent);
break;
//點選繫結Service
case R.id.bindService:
//構建繫結服務的Intent物件
Intent bindIntent = new Intent(this, MyService.class);
//呼叫bindService()方法,以此停止服務
bindService(bindIntent,connection,BIND_AUTO_CREATE);
//引數說明
//第一個引數:Intent物件
//第二個引數:上面建立的Serviceconnection例項
//第三個引數:標誌位
//這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動建立Service
//這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行
break;
//點選解綁Service
case R.id.unbindService:
//呼叫unbindService()解綁服務
//引數是上面建立的Serviceconnection例項
unbindService(connection);
break;
default:
break;
}
}
}
2.2.2 Demo
carson.ho的Github地址:Demo_for_Service
2.3 前臺Service
前臺Service和後臺Service(普通)最大的區別就在於:
- 前臺Service在下拉通知欄有顯示通知(如下圖),但後臺Service沒有;
- 前臺Service優先順序較高,不會由於系統記憶體不足而被回收;後臺Service優先順序較低,當系統出現記憶體不足情況時,很有可能會被回收
2.3.1 具體使用
用法很簡單,只需要在原有的Service類對onCreate()方法進行稍微修改即可,如下圖:
@Override
public void onCreate() {
super.onCreate();
System.out.println("執行了onCreat()");
//新增下列程式碼將後臺Service變成前臺Service
//構建"點選通知後開啟MainActivity"的Intent物件
Intent notificationIntent = new Intent(this,MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
//新建Builer物件
Notification.Builder builer = new Notification.Builder(this);
builer.setContentTitle("前臺服務通知的標題");//設定通知的標題
builer.setContentText("前臺服務通知的內容");//設定通知的內容
builer.setSmallIcon(R.mipmap.ic_launcher);//設定通知的圖示
builer.setContentIntent(pendingIntent);//設定點選通知後的操作
Notification notification = builer.getNotification();//將Builder物件轉變成普通的notification
startForeground(1, notification);//讓Service變成前臺Service,並在系統的狀態列顯示出來
}
2.3.2 測試結果
執行後,當點選Start Service或Bind Service按鈕,Service就會以前臺Service的模式啟動(通知欄上有通知),如下圖
3. 使用場景
各種Service的使用場景請看下圖:
Service 與 Thread的區別
- 結論:
Service
與Thread
無任何關係 - 之所以有不少人會把它們聯絡起來,主要因為
Service
的後臺概念
後臺:後臺任務執行完全不依賴
UI
,即使Activity被銷燬 / 程式被關閉,只要程式還在,後臺任務就可繼續執行
- 關於二者的異同,具體如下圖:
- 一般會將
Service
和Thread
聯合著用,即在Service
中再建立一個子執行緒(工作執行緒)去處理耗時操作邏輯,如下程式碼:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//新建工作執行緒
new Thread(new Runnable() {
@Override
public void run() {
// 開始執行後臺任務
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
class MyBinder extends Binder {
public void service_connect_Activity() {
//新建工作執行緒
new Thread(new Runnable() {
@Override
public void run() {
// 執行具體的下載任務
}
}).start();
}
}
連結:https://www.jianshu.com/p/d963c55c3ab9
連結:https://www.jianshu.com/p/e04c4239b07e
連結:https://blog.csdn.net/andrexpert/article/details/53485360
https://www.jianshu.com/p/d870f99b675c
相關文章
- Android之ServiceAndroid
- Android之Service設定android:process作用Android
- 十四、Android效能優化之ServiceAndroid優化
- k8s之Service詳解-Service使用K8S
- Android 四大元件之 ServiceAndroid元件
- Android 四大元件之" Service "Android元件
- Android效能優化(十)之App瘦身攻略Android優化APP
- Android ServiceAndroid
- Android四大元件之Service篇Android元件
- Android Service 服務(一)—— ServiceAndroid
- Android四大元件之Service,以及IntentServiceAndroid元件Intent
- Android知識點回顧之Service基礎Android
- Android探索之Service全面回顧及總結Android
- Android基礎及應用 Service的使用Android
- Android:Retrofit 2.0 使用攻略(含例項講解)Android
- Android Service SecurityAndroid
- Android Intent ServiceAndroidIntent
- Android學習之四大元件(二)——serviceAndroid元件
- Android中bindService的使用及Service生命週期Android
- Android中startService的使用及Service生命週期Android
- Android Service完全解析Android
- 淺談 Android ServiceAndroid
- Android:Service詳解Android
- Android中Service概述Android
- android service詳解Android
- Android開發實踐:使用Service還是ThreadAndroidthread
- Android Q 提前適配攻略Android
- Android總結篇系列:Android ServiceAndroid
- Android中的Web ServiceAndroidWeb
- Android Service詳解(二)Android
- Android Service詳解(一)Android
- Android中Service總結Android
- Android-Service詳解Android
- Android Service 訪問安全Android
- Android Activity/Service/Broadcaster三大元件之間互相呼叫AndroidAST元件
- Android:這是一份全面&詳細的Webview使用攻略AndroidWebView
- Windows API 之 Windows ServiceWindowsAPI
- RAC筆記之service筆記