四大組件之Service
AndroidAZ系列有以下目的:
- Android程序猿的面試(初級,中級,高級,資深),拿到滿意的offer。
- Android程序猿學(xué)習(xí)進階。
標記說明:因為筆者是列出所有的Android知識點,因此面試不需要看那么多內(nèi)容,如果是面試的知識點。筆者會加上標記Face,而如果不是面試的知識點,筆者會加上No標記,它是要學(xué)的東西;然后筆者將Android面試者或者面試者分為4個等級,初級A1,中級A2,高級A3,資深A(yù)4,如果這個知識點是所有等級的范圍,那么筆者將會以all標記上。因此進階路線就是A1->A2->A3->A4。也是面試者挑選的復(fù)習(xí)范圍,假如你是中級程序員,那么你面試要看的內(nèi)容就是包含A2&Face的標記。
All : 所有的Android工程師都看。
A1: 初級Android工程師。
A2: 中級Android工程師。
A3: 高級Android工程師。
A4: 資深A(yù)ndroid工程師。
Face: 是面試的知識點。
No: 面試基本遇不到。
1.Service 是什么
Android Service是Android四大組件之一,它主要用來執(zhí)行一些不與用戶交互的長期運行的任務(wù). 服務(wù)的運行不依賴于任何用戶界面,即使程序被切換到后臺,或者用戶打開了另一個應(yīng)用程序,服務(wù)仍然能夠保持正常運行. 另外Service并不是運行在單獨線程中,而是主線程中。所以盡量要避免耗時操作。
2.Service和線程的區(qū)別
2.1 線程的用法
-
方法一:
class MyThread extends Thread{ @Override public void run(){ // 耗時操作 } } new MyThread().start(); -
方法二:
class Mythread implements Runnable{ @Override public void run(){ // 耗時操作 } } Mythread mythread = new Mythread(); new Thead(mythread).start();
2.2 在子線程中更新UI
-
方法一:
public static final int MSG_ID = 100; private Handler handler = new Handler(){ public void handleMessage(Message msg){ switch(msg.what){ case MSG_ID: // 更新UI break; default: break; } } } new Thread(new Runnable(){ @Override public void run(){ Message message = new Message(); message.what = MSG_ID; handler.sendMessage(message); } }).start(); -
方法二:
這里的原理和方法一是一樣的,只是進行了封裝
@android.webkit.JavascriptInterface public void actionFromJs() { mMainView.getActivity().runOnUiThread(new Runnable() { @Override public void run() { MusicPlayerHelper.getIntence(mMainView.getContext().getApplicationContext()).stopBgSound(); Intent intent = new Intent(); intent.setClass(mMainView.getContext(), NocviceActivity.class);//打開一個activity mMainView.getActivity().startActivity(intent); } }); }
2.3 服務(wù)的用法
- 定義一個服務(wù)
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();
}
}
- 在AndroidManifest.xml中進行注冊
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:lable="@string/app_name"
android:suppertsRtl="true"
android:theme="@style/AppTheme">
...
<service
android:name=".MyService"
android:enable="true"
android:exported="true">
</service>
</application>
- 啟動服務(wù)
Intent startIntent = new Intent(mContext,MyService.class);
mContext.startService(startIntent);
- 停止服務(wù)
Intent stopIntent = new Intent(mContext,MyService.class);
mContext.stopService(startIntent);
Service和Thread的區(qū)別
-
Service
在后臺用來執(zhí)行長時間運行操作的應(yīng)用組件
Service的生命周期在主線程中執(zhí)行,如果要執(zhí)行耗時操作,需要開啟一個分線程
應(yīng)用退出,Service也不會停止
再次啟動應(yīng)用時,還可以和正在運行的Service通信
-
Thread
用來開啟一個分線程的類,用來做耗時操作
Thread類的run()在分線程執(zhí)行
應(yīng)用退出,Thread也不會停止
再次啟動應(yīng)用,不能再控制之前的Thread對象
-
詳細解釋
其實這跟 android 的系統(tǒng)機制有關(guān),我們先拿Thread 來說。Thread 的運行是獨立于 Activity 的,也就是說當一個 Activity 被 finish 之后,如果你沒有主動停止 Thread 或者 Thread 里的 run 方法沒有執(zhí)行完畢的話,Thread 也會一直執(zhí)行。因此這里會出現(xiàn)一個問題:當 Activity 被 finish 之后,你不再持有該 Thread 的引用。另一方面,你沒有辦法在不同的 Activity 中對同一 Thread 進行控制
如果你的 Thread 需要不停地隔一段時間就要連接服務(wù)器做某種同步的話,該 Thread 需要在 Activity 沒有start的時候也在運行。這個時候當你 start 一個 Activity 就沒有辦法在該 Activity 里面控制之前創(chuàng)建的 Thread。因此你便需要創(chuàng)建并啟動一個 Service ,在 Service 里面創(chuàng)建、運行并控制該 Thread,這樣便解決了該問題(因為任何 Activity 都可以控制同一 Service,而系統(tǒng)也只會創(chuàng)建一個對應(yīng) Service 的實例)
因此你可以把 Service 想象成一種消息服務(wù),而你可以在任何有 Context 的地方調(diào)用Context.startService、Context.stopService、Context.bindService,Context.unbindService,來控制它,你也可以在 Service 里注冊 BroadcastReceiver,在其他地方通過發(fā)送 broadcast 來控制它,當然這些都是 Thread 做不到的
3.Service的生命周期

3.1 startService
-
啟動Service服務(wù)
單次:startService() —> onCreate() —> onStartCommand()
多次:startService() —> onCreate() —> onStartCommand() —> onStartCommand()
-
停止Service服務(wù)
stopService() —> onDestroy()
3.2 bindService
-
綁定Service服務(wù)
bindService() —> onCreate() —> onBind()
-
解綁Service服務(wù)
unbindService() —> onUnbind() —> onDestroy()
-
啟動綁定Service服務(wù)
startService() —> onCreate() —> onStartCommand() —> bindService() —> onBind()
-
解綁停止Service服務(wù)
unbindService() —> onUnbind() —> stopService() —> onDestroy()
-
解綁綁定Service服務(wù)
unbindService() —> onUnbind(ture) —> bindService() —> onRebind()
3.3 onStartCommand()和onStart()區(qū)別
每調(diào)用一次startService()方法, onStartCommand()就會執(zhí)行一次
onstart()方法是在android2.0一下的版本中使用。而在android2.0以上則使用onstartCommand()方法。它們兩個方法放在一起使用時,不會產(chǎn)生沖突
4.Intent Service的使用
Intent Service時一個異步的 會自動停止的服務(wù)
public class MyIntentService extends IntentService{
public MyIntentService(){
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent){
// 耗時操作
Log.d("MyIntentService","This is is" + Thread.currentThread().getId());
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("MyIntentService","onDestroy executed");
}
}
這里首先要提供一個無參的構(gòu)造函數(shù),并且必須在其內(nèi)部調(diào)用父類的構(gòu)造函數(shù).然后要在子類中去實現(xiàn)onHandleIntent()這個抽象方法,在這個方法里執(zhí)行耗時邏輯,而不用擔心ANR的問題,因為這個方法已經(jīng)是在子線程中運行了.
5. Service使用場景
Service是一個應(yīng)用程序中不可見的組件,用于處理運行時間長或者不需要用戶交互的任務(wù),比如一個股票應(yīng)用,應(yīng)用程序關(guān)掉了但是要給用戶實時提供最新的數(shù)據(jù),這時就可以使用Service