Android 面试 - 有关Service的面试题
1.Service是什么
Service(服務(wù))是一個可以在后臺執(zhí)行長時間運行操作而沒有用戶界面的應(yīng)用組件。
注:Service是運行在主線程中的,不能進行耗時操作
2.Service和Thread的區(qū)別
Thread 程序執(zhí)行的最小單元,我們可以用它執(zhí)行一些異步操作,相對獨立而Service依托于他所在的主線程上,并不獨立
3.為什么說Service 是后臺服務(wù)
因為 Service沒有UI,用戶無法感知 ,Service 和 Activity 是兩個不同的線程,他們之間要通過ICP通信
4.開啟Service 的兩種方式
startService:
(1)定義一個類繼承Service
(2)在Mainfest.xml 配置文件中配置該Service
(3)使用Context的startService(Intent) 方法啟動Service,傳進去的參數(shù)是Intent
(4)不使用時調(diào)用stopService(Intent)
當Service 被啟動之后將無限的運行下去,即使Activity被銷毀也不會停止,除非手動停止 Service
bindService:
Activity 和 Service 進行綁定,如果綁定全部取消之后,這個Service自動被銷毀
代碼實例:
MyService.java
MainActivity.java
package com.example.demo20220303;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Trace; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button startBtn;private Button stopBtn;private Button bindBtn;private Button unBindBtn;private EditText editText;private TextView textView;private Intent startIntent;private boolean isBound = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}public void initView() {startBtn = findViewById(R.id.main_start_btn);stopBtn = findViewById(R.id.main_stop_btn);bindBtn = findViewById(R.id.main_bind_btn);unBindBtn = findViewById(R.id.main_unbind_btn);editText = findViewById(R.id.main_et);textView = findViewById(R.id.main_tv);startBtn.setOnClickListener(this);stopBtn.setOnClickListener(this);bindBtn.setOnClickListener(this);unBindBtn.setOnClickListener(this);}private ServiceConnection connection = new ServiceConnection() {// 當服務(wù)連接的時候調(diào)用 onServiceConnected 獲取 IBinder 中的公共方法進行使用@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {isBound = true;MyService.MyBinder myBinder = (MyService.MyBinder) service;String text = myBinder.getService().getString();Log.i("sss", text);}// onServiceDisconnected() 在連接正常關(guān)閉的情況下是不會被調(diào)用的.// 該方法只在Service 被破壞了或者被殺死的時候調(diào)用. 例如, 系統(tǒng)資源不足, 要關(guān)閉一些Services// 剛好連接綁定的 Service 是被關(guān)閉者之一, 這個時候onServiceDisconnected() 就會被調(diào)用.@Overridepublic void onServiceDisconnected(ComponentName name) {isBound = false;}};@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.main_start_btn://啟動服務(wù)startIntent = new Intent(MainActivity.this,MyService.class);this.startService(startIntent);break;case R.id.main_stop_btn://關(guān)閉服務(wù)this.stopService(startIntent);break;case R.id.main_bind_btn:Intent bindIntent = new Intent(MainActivity.this,MyService.class);this.bindService(bindIntent,connection,BIND_AUTO_CREATE);break;case R.id.main_unbind_btn:if(isBound) {unbindService(connection);}break;default:}} }activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><com.example.demo20220303.view.MyTittleViewandroid:id="@+id/customview_title"android:layout_width="match_parent"android:layout_height="wrap_content"></com.example.demo20220303.view.MyTittleView><EditTextandroid:id="@+id/main_et"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextViewandroid:text=""android:gravity="center"android:textSize="30sp"android:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/main_tv"/><Buttonandroid:id="@+id/main_start_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="啟動服務(wù)" /><Buttonandroid:id="@+id/main_stop_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="停止服務(wù)" /><Buttonandroid:id="@+id/main_bind_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="綁定服務(wù)" /><Buttonandroid:id="@+id/main_unbind_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="取消綁定服務(wù)" /></LinearLayout >點擊啟動服務(wù)按鈕:
I/onCreate:: onCreate ways I/onStartCommand:: onStartCommand ways點擊停止服務(wù)按鈕:
I/onDestroy:: onDestroy ways點擊綁定服務(wù)按鈕:
I/onCreate:: onCreate ways I/onBind:: onBind ways I/sss: binder bangding!!!點擊取消綁定服務(wù)按鈕
I/onUnbind:: onUnbind ways I/onDestroy:: onDestroy ways5.Service的周期
推薦博主地址:
https://www.cnblogs.com/huihuizhang/p/7623760.html
與Activity類似,Service也有自己的生命周期函數(shù),在不同的時刻,系統(tǒng)會調(diào)用對應(yīng)的Service生命周期函數(shù),不過與Activity聲明周期相比,Service的聲明周期更加簡單,我們通過官方給出的一張圖片來體會一下:
這里我們總結(jié)一下:
1). 被啟動的服務(wù)的生命周期:如果一個Service被某個Activity 調(diào)用 Context.startService 方法啟動,那么不管是否有Activity使用bindService綁定或unbindService解除綁定到該Service,該Service都在后臺運行。如果一個Service被startService 方法多次啟動,那么onCreate方法只會調(diào)用一次,onStart將會被調(diào)用多次(對應(yīng)調(diào)用startService的次數(shù)),并且系統(tǒng)只會創(chuàng)建Service的一個實例(因此你應(yīng)該知道只需要一次stopService調(diào)用)。該Service將會一直在后臺運行,而不管對應(yīng)程序的Activity是否在運行,直到被調(diào)用stopService,或自身的stopSelf方法。當然如果系統(tǒng)資源不足,android系統(tǒng)也可能結(jié)束服務(wù)。
2). 被綁定的服務(wù)的生命周期:如果一個Service被某個Activity 調(diào)用 Context.bindService 方法綁定啟動,不管調(diào)用 bindService 調(diào)用幾次,onCreate方法都只會調(diào)用一次,同時onStart方法始終不會被調(diào)用。當連接建立之后,Service將會一直運行,除非調(diào)用Context.unbindService 斷開連接或者之前調(diào)用bindService 的 Context 不存在了(如Activity被finish的時候),系統(tǒng)將會自動停止Service,對應(yīng)onDestroy將被調(diào)用。
3). 被啟動又被綁定的服務(wù)的生命周期:如果一個Service又被啟動又被綁定,則該Service將會一直在后臺運行。并且不管如何調(diào)用,onCreate始終只會調(diào)用一次,對應(yīng)startService調(diào)用多少次,Service的onStart便會調(diào)用多少次。調(diào)用unbindService將不會停止Service,而必須調(diào)用 stopService 或 Service的 stopSelf 來停止服務(wù)。
4). 當服務(wù)被停止時清除服務(wù):當一個Service被終止(1、調(diào)用stopService;2、調(diào)用stopSelf;3、不再有綁定的連接(沒有被啟動))時,onDestroy方法將會被調(diào)用,在這里你應(yīng)當做一些清除工作,如停止在Service中創(chuàng)建并運行的線程。
特別注意:
1、你應(yīng)當知道在調(diào)用 bindService 綁定到Service的時候,你就應(yīng)當保證在某處調(diào)用 unbindService 解除綁定(盡管 Activity 被 finish 的時候綁定會自 動解除,并且Service會自動停止);
2、你應(yīng)當注意 使用 startService 啟動服務(wù)之后,一定要使用 stopService停止服務(wù),不管你是否使用bindService;
3、同時使用 startService 與 bindService 要注意到,Service 的終止,需要unbindService與stopService同時調(diào)用,才能終止 Service,不管 startService 與 bindService 的調(diào)用順序,如果先調(diào)用 unbindService 此時服務(wù)不會自動終止,再調(diào)用 stopService 之后服務(wù)才會停止,如果先調(diào)用 stopService 此時服務(wù)也不會終止,而再調(diào)用 unbindService 或者 之前調(diào)用 bindService 的 Context 不存在了(如Activity 被 finish 的時候)之后服務(wù)才會自動停止;
4、當在旋轉(zhuǎn)手機屏幕的時候,當手機屏幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉(zhuǎn)的話,旋轉(zhuǎn)其實是 Activity 的重新創(chuàng)建,因此旋轉(zhuǎn)之前的使用 bindService 建立的連接便會斷開(Context 不存在了),對應(yīng)服務(wù)的生命周期與上述相同。
5、在 sdk 2.0 及其以后的版本中,對應(yīng)的 onStart 已經(jīng)被否決變?yōu)榱?onStartCommand,不過之前的 onStart 任然有效。這意味著,如果你開發(fā)的應(yīng)用程序用的 sdk 為 2.0 及其以后的版本,那么你應(yīng)當使用 onStartCommand 而不是 onStart。
生命周期方法說明
onStartCommand()
當另一個組件(如 Activity)通過調(diào)用 startService() 請求啟動服務(wù)時,系統(tǒng)將調(diào)用此方法。一旦執(zhí)行此方法,服務(wù)即會啟動并可在后臺無限期運行。 如果您實現(xiàn)此方法,則在服務(wù)工作完成后,需要由您通過調(diào)用 stopSelf() 或 stopService() 來停止服務(wù)。(如果您只想提供綁定,則無需實現(xiàn)此方法。)
onBind()
當另一個組件想通過調(diào)用 bindService() 與服務(wù)綁定(例如執(zhí)行 RPC)時,系統(tǒng)將調(diào)用此方法。在此方法的實現(xiàn)中,您必須通過返回 IBinder 提供一個接口,供客戶端用來與服務(wù)進行通信。請務(wù)必實現(xiàn)此方法,但如果您并不希望允許綁定,則應(yīng)返回 null。
onCreate()
首次創(chuàng)建服務(wù)時,系統(tǒng)將調(diào)用此方法來執(zhí)行一次性設(shè)置程序(在調(diào)用 onStartCommand() 或 onBind() 之前)。如果服務(wù)已在運行,則不會調(diào)用此方法。
onDestroy()
當服務(wù)不再使用且將被銷毀時,系統(tǒng)將調(diào)用此方法。服務(wù)應(yīng)該實現(xiàn)此方法來清理所有資源,如線程、注冊的偵聽器、接收器等。 這是服務(wù)接收的最后一個調(diào)用。
總結(jié)
以上是生活随笔為你收集整理的Android 面试 - 有关Service的面试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STEMA 考试每日一练 2020.12
- 下一篇: Android 面试题集整理