Android 面试 - 有关Service的面试题
1.Service是什么
Service(服務)是一個可以在后臺執行長時間運行操作而沒有用戶界面的應用組件。
注:Service是運行在主線程中的,不能進行耗時操作
2.Service和Thread的區別
Thread 程序執行的最小單元,我們可以用它執行一些異步操作,相對獨立而Service依托于他所在的主線程上,并不獨立
3.為什么說Service 是后臺服務
因為 Service沒有UI,用戶無法感知 ,Service 和 Activity 是兩個不同的線程,他們之間要通過ICP通信
4.開啟Service 的兩種方式
startService:
(1)定義一個類繼承Service
(2)在Mainfest.xml 配置文件中配置該Service
(3)使用Context的startService(Intent) 方法啟動Service,傳進去的參數是Intent
(4)不使用時調用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() {// 當服務連接的時候調用 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() 在連接正常關閉的情況下是不會被調用的.// 該方法只在Service 被破壞了或者被殺死的時候調用. 例如, 系統資源不足, 要關閉一些Services// 剛好連接綁定的 Service 是被關閉者之一, 這個時候onServiceDisconnected() 就會被調用.@Overridepublic void onServiceDisconnected(ComponentName name) {isBound = false;}};@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.main_start_btn://啟動服務startIntent = new Intent(MainActivity.this,MyService.class);this.startService(startIntent);break;case R.id.main_stop_btn://關閉服務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="啟動服務" /><Buttonandroid:id="@+id/main_stop_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="停止服務" /><Buttonandroid:id="@+id/main_bind_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="綁定服務" /><Buttonandroid:id="@+id/main_unbind_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="取消綁定服務" /></LinearLayout >點擊啟動服務按鈕:
I/onCreate:: onCreate ways I/onStartCommand:: onStartCommand ways點擊停止服務按鈕:
I/onDestroy:: onDestroy ways點擊綁定服務按鈕:
I/onCreate:: onCreate ways I/onBind:: onBind ways I/sss: binder bangding!!!點擊取消綁定服務按鈕
I/onUnbind:: onUnbind ways I/onDestroy:: onDestroy ways5.Service的周期
推薦博主地址:
https://www.cnblogs.com/huihuizhang/p/7623760.html
與Activity類似,Service也有自己的生命周期函數,在不同的時刻,系統會調用對應的Service生命周期函數,不過與Activity聲明周期相比,Service的聲明周期更加簡單,我們通過官方給出的一張圖片來體會一下:
這里我們總結一下:
1). 被啟動的服務的生命周期:如果一個Service被某個Activity 調用 Context.startService 方法啟動,那么不管是否有Activity使用bindService綁定或unbindService解除綁定到該Service,該Service都在后臺運行。如果一個Service被startService 方法多次啟動,那么onCreate方法只會調用一次,onStart將會被調用多次(對應調用startService的次數),并且系統只會創建Service的一個實例(因此你應該知道只需要一次stopService調用)。該Service將會一直在后臺運行,而不管對應程序的Activity是否在運行,直到被調用stopService,或自身的stopSelf方法。當然如果系統資源不足,android系統也可能結束服務。
2). 被綁定的服務的生命周期:如果一個Service被某個Activity 調用 Context.bindService 方法綁定啟動,不管調用 bindService 調用幾次,onCreate方法都只會調用一次,同時onStart方法始終不會被調用。當連接建立之后,Service將會一直運行,除非調用Context.unbindService 斷開連接或者之前調用bindService 的 Context 不存在了(如Activity被finish的時候),系統將會自動停止Service,對應onDestroy將被調用。
3). 被啟動又被綁定的服務的生命周期:如果一個Service又被啟動又被綁定,則該Service將會一直在后臺運行。并且不管如何調用,onCreate始終只會調用一次,對應startService調用多少次,Service的onStart便會調用多少次。調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。
4). 當服務被停止時清除服務:當一個Service被終止(1、調用stopService;2、調用stopSelf;3、不再有綁定的連接(沒有被啟動))時,onDestroy方法將會被調用,在這里你應當做一些清除工作,如停止在Service中創建并運行的線程。
特別注意:
1、你應當知道在調用 bindService 綁定到Service的時候,你就應當保證在某處調用 unbindService 解除綁定(盡管 Activity 被 finish 的時候綁定會自 動解除,并且Service會自動停止);
2、你應當注意 使用 startService 啟動服務之后,一定要使用 stopService停止服務,不管你是否使用bindService;
3、同時使用 startService 與 bindService 要注意到,Service 的終止,需要unbindService與stopService同時調用,才能終止 Service,不管 startService 與 bindService 的調用順序,如果先調用 unbindService 此時服務不會自動終止,再調用 stopService 之后服務才會停止,如果先調用 stopService 此時服務也不會終止,而再調用 unbindService 或者 之前調用 bindService 的 Context 不存在了(如Activity 被 finish 的時候)之后服務才會自動停止;
4、當在旋轉手機屏幕的時候,當手機屏幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉的話,旋轉其實是 Activity 的重新創建,因此旋轉之前的使用 bindService 建立的連接便會斷開(Context 不存在了),對應服務的生命周期與上述相同。
5、在 sdk 2.0 及其以后的版本中,對應的 onStart 已經被否決變為了 onStartCommand,不過之前的 onStart 任然有效。這意味著,如果你開發的應用程序用的 sdk 為 2.0 及其以后的版本,那么你應當使用 onStartCommand 而不是 onStart。
生命周期方法說明
onStartCommand()
當另一個組件(如 Activity)通過調用 startService() 請求啟動服務時,系統將調用此方法。一旦執行此方法,服務即會啟動并可在后臺無限期運行。 如果您實現此方法,則在服務工作完成后,需要由您通過調用 stopSelf() 或 stopService() 來停止服務。(如果您只想提供綁定,則無需實現此方法。)
onBind()
當另一個組件想通過調用 bindService() 與服務綁定(例如執行 RPC)時,系統將調用此方法。在此方法的實現中,您必須通過返回 IBinder 提供一個接口,供客戶端用來與服務進行通信。請務必實現此方法,但如果您并不希望允許綁定,則應返回 null。
onCreate()
首次創建服務時,系統將調用此方法來執行一次性設置程序(在調用 onStartCommand() 或 onBind() 之前)。如果服務已在運行,則不會調用此方法。
onDestroy()
當服務不再使用且將被銷毀時,系統將調用此方法。服務應該實現此方法來清理所有資源,如線程、注冊的偵聽器、接收器等。 這是服務接收的最后一個調用。
總結
以上是生活随笔為你收集整理的Android 面试 - 有关Service的面试题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STEMA 考试每日一练 2020.12
- 下一篇: Android 面试题集整理