前言
上回小米面試問到Servic的時候懵了一下,因為基本很少用到淤井,現(xiàn)在就再次來復習一下己英。
正文
Service的生命周期
Service屬于Android的四大組件之一,運行在主線程當中赞警,適用場景在不需要跟用戶交互而又需要長期運行的任務的時候可以用到Service弄跌。
Service的使用方法主要分為兩種甲喝,
startService()
和bindService()
,兩種的生命周期稍微不一樣铛只,這里著重說幾點俺猿。
1.每調(diào)用一次startService()
就會調(diào)用一次onStartCommand()
生命周期,但是onCreate是只調(diào)用一次的格仲。
2.Service通過BindService()
綁定后,將會一直運行下去诵冒,直到使用unBindService()
方法或者它的Activit被銷毀才回結(jié)束凯肋。
3.如果方法已經(jīng)被綁定了,在沒有解綁的情況下汽馋,stopService()
是無法停止服務的侮东,就算生命周期走到了onDestroy()
也無法停止。
4.如果一開始先調(diào)用startService()
方法后再去調(diào)用BindService()
后豹芯,需要同時StopService()
和unBIndService()
方法才能同時銷毀悄雅。
如何使用Service
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
首先看代碼,使用一個Service就是要繼承這個類铁蹈,然后必須重寫onBind
這個方法宽闲,我們先暫時不看這個方法,那一些處理業(yè)務邏輯的方法要寫在哪呢?這時我們就可以重寫Service中其他的一些方法了容诬。
public class MyService extends Service {
public MyService() {
}
//先不看這個方法
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
這里又重寫了三個方法娩梨,onStartCommand()
我們已經(jīng)講過了,每次啟動一次Service就會調(diào)用一次這個方法览徒,onCreate()
會在服務創(chuàng)建的時候調(diào)用狈定,onDestroy()
就會在服務銷毀的時候調(diào)用。
一般來說邏輯業(yè)務都是寫在onStartCommand()
方法里的习蓬,需要銷毀資源的時候就是在onDestroy()
里面纽什。需要注意的是,每一個Service和Activity一樣躲叼,都需要再AndroidManifest.xml進行注冊才能使用芦缰。
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
啟動服務
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button b1, b2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1 = findViewById(R.id.button1);
b2 = findViewById(R.id.button2);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
Intent startIntent = new Intent(this,MyService.class);
startService(startIntent);
break;
case R.id.button2:
Intent stopIntent = new Intent(this,MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
創(chuàng)建兩個button,一個啟動服務一個停止服務押赊,我們通過Intent來進行實現(xiàn)的饺藤。啟動服務的時候服務會一直在運行狀態(tài),知道點擊了停止服務的按鈕服務才會停止下來流礁,那有沒有其他的辦法不通過停止按鈕來進行服務停止呢涕俗。這時候只要在Service的任何要停止的位置調(diào)用stopSelf()
就可以停止服務了。
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Log.d("ServiceDemo","onCreate:服務創(chuàng)建");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ServiceDemo","onStartCommand:服務在執(zhí)行");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("ServiceDemo","onDestroy:服務銷毀");
}
}
Activity和Service進行通信
我在這里寫一個例子舉例這兩個怎么進行交互神帅,因為通過剛才的學習再姑,發(fā)現(xiàn)Activity只負責啟動和停止Service后好像就沒什么用的,這時候就用到我們剛才忽略的onBind()
方法了找御。
public class DownLoadBinder extends Binder {
public void startDownLoad(){
Log.d("","startDownLoad excuted");
}
public int getDonwload(){
Log.d("","getDonwload excuted");
return 0;
}
}
使用這個方法之前我們需要創(chuàng)建一個Binder對象一起配合實現(xiàn)功能元镀,我們這里模擬一個下載功能,創(chuàng)建一個DownLoadBinder
來繼承Binder來實現(xiàn)霎桅。
public class MyService extends Service {
private DownLoadBinder downLoadBinder = new DownLoadBinder();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return downLoadBinder;
}
......
}
然后實例化這個類栖疑,直接在onBind()
方法里返回就好了,接下來在MainActivity修改滔驶。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button b1, b2, bind, unBind;
private DownLoadBinder downLoadBinder = new DownLoadBinder();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//這兩個是啟動和開始服務按鈕
b1 = findViewById(R.id.button1);
b2 = findViewById(R.id.button2);
//這兩個是綁定和解綁服務按鈕
bind = findViewById(R.id.bind);
unBind = findViewById(R.id.unBind);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
bind.setOnClickListener(this);
unBind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.button2:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
case R.id.bind:
//綁定服務
Intent bindService = new Intent(this,MyService.class);
bindService(bindService,connection,BIND_AUTO_CREATE);
break;
case R.id.unBind:
unbindService(connection);
//解綁服務
break;
default:
break;
}
}
//創(chuàng)建ServiceConnect
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downLoadBinder = (DownLoadBinder) service;
downLoadBinder.startDownLoad();
downLoadBinder.getDonwload();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
這里首先創(chuàng)建一個ServiceConnection的匿名類遇革,重寫兩個onServiceConnected()
和onServiceDisconnected()
這兩個方法,然后通過綁定服務的時候調(diào)用揭糕,這時候我們就可以在Activity場景中調(diào)用DownloadBinder的方法了萝快,在綁定的方法里面需要接受三個參數(shù),第一就是剛剛構(gòu)建的Intent對象著角,第二個就是創(chuàng)建出來的ServiceConnection實例揪漩,第三個是標志位,這里傳入的BIND_AUTO_CREATE表示綁定后就會自動創(chuàng)建服務吏口,這時候服務才會開始執(zhí)行奄容。MyService不僅能和這個Activity進行綁定沙廉,跟其它Activity進行綁定也是可以的北发。
InetntService
剛剛也說過Service是運行在主線程的勺美,所以說如果運行一些很耗時的服務谣拣,就很容易造成ANR(Application not Responding),這個時候就需要多線程的幫助了,而這Intent就是為此而生的叁怪。我們可以把這個類看成是HandlerThread和Service的結(jié)合體审葬。在這個類里開啟一個子線程,然后做一些耗時的操作奕谭。它是一個異步的會自動停止的類涣觉。
public class MyIntentService extends IntentService {
public MyIntentService(String name) {
super(name);
}
@Override
protected void onHandleIntent(@androidx.annotation.Nullable @Nullable Intent intent) {
//具體邏輯
}
}
使用方法和Service差不多,耗時的操作寫在onHandleIntent()
里血柳,它首先要提供一個構(gòu)造函數(shù)官册,然后調(diào)用父類的構(gòu)造函數(shù)。IntentService也是可以啟動多次的难捌,每次也只會執(zhí)行一個工作線程膝宁,然后執(zhí)行完在執(zhí)行下一個,依次進行下去根吁。關(guān)于IntentService一些具體的使用注意员淫,后面會寫一章源碼分析來進行講解。
參考
- [郭霖] 第一行代碼Android(第二版)