面試寶典|Android基礎(chǔ)(二)

本篇主要講解數(shù)據(jù)庫及IPC相關(guān)

數(shù)據(jù)存儲相關(guān)

Q:Android中提供哪些數(shù)據(jù)持久存儲的方法?

  • 技術(shù)點:數(shù)據(jù)持久化
  • 思路:分條解釋每種數(shù)據(jù)持久存儲的特點
  • 參考回答:Android平臺實現(xiàn)數(shù)據(jù)存儲的常見幾種方式:
    • File 文件存儲:寫入和讀取文件的方法和 Java中實現(xiàn)I/O的程序一樣。
    • SharedPreferences存儲:一種輕型的數(shù)據(jù)存儲方式,常用來存儲一些簡單的配置信息,本質(zhì)是基于XML文件存儲key-value鍵值對數(shù)據(jù)。
    • SQLite數(shù)據(jù)庫存儲:一款輕量級的關(guān)系型數(shù)據(jù)庫,它的運算速度非常快,占用資源很少,在存儲大量復(fù)雜的關(guān)系型數(shù)據(jù)的時可以使用。
    • ContentProvider:四大組件之一,用于數(shù)據(jù)的存儲和共享,不僅可以讓不同應(yīng)用程序之間進行數(shù)據(jù)共享,還可以選擇只對哪一部分數(shù)據(jù)進行共享,可保證程序中的隱私數(shù)據(jù)不會有泄漏風(fēng)險。

Q:Java中的I/O流讀寫怎么做?

  • 技術(shù)點:數(shù)據(jù)持久化(文件存儲)
  • 思路:大致介紹核心類和核心方法
  • 參考回答:和 Java中實現(xiàn)I/O的程序是一樣的,Context類中提供了openFileInput()和openFileOutput()方法來打開數(shù)據(jù)文件里的文件IO流

Q:SharePreferences適用情形?使用中需要注意什么?

  • 技術(shù)點:數(shù)據(jù)持久化(SharePreferences存儲)
  • 參考回答:SharePreferences是一種輕型的數(shù)據(jù)存儲方式,適用于存儲一些簡單的配置信息,如int、string、boolean、float和long。由于系統(tǒng)對SharedPreferences的讀/寫有一定的緩存策略,即在內(nèi)存中有一份該文件的緩存,因此在多進程模式下,其讀/寫會變得不可靠,甚至丟失數(shù)據(jù)。
  • 引申:談?wù)凙ndroid中多進程通信(Binder)

Q:了解SQLite中的事務(wù)處理嗎?是如何做的?

  • 技術(shù)點:數(shù)據(jù)持久化(SQLite)
  • 參考回答:SQLite在做CRDU操作時都默認開啟了事務(wù),然后把SQL語句翻譯成對應(yīng)的SQLiteStatement并調(diào)用其相應(yīng)的CRUD方法,此時整個操作還是在rollback journal這個臨時文件上進行,只有操作順利完成才會更新.db數(shù)據(jù)庫,否則會被回滾。
  • 引申:談?wù)勅绾文7耂QLite中事務(wù)的思想更高效進行批量操作

Q:使用SQLite做批量操作有什么好的方法嗎?

  • 技術(shù)點:數(shù)據(jù)持久化(SQLite)
  • 思路:模仿SQLite的事務(wù)處理
  • 參考回答:使用SQLiteDatabase的beginTransaction()方法開啟一個事務(wù),將批量操作SQL語句轉(zhuǎn)化成SQLiteStatement并進行批量操作,結(jié)束后endTransaction()

Q:如果現(xiàn)在要刪除SQLite中表的一個字段如何做?

  • 技術(shù)點:數(shù)據(jù)持久化(SQLite)
  • 參考回答:SQLite數(shù)據(jù)庫只允許增加表字段而不允許修改和刪除表字段,只能采取復(fù)制表思想,即創(chuàng)建一個新表保留原表想要的字段、再將原表刪除

Q:使用SQLite時會有哪些優(yōu)化操作?

  • 技術(shù)點:數(shù)據(jù)持久化(SQLite)
  • 思路:列舉可優(yōu)化點
  • 參考回答:
    • 使用事務(wù)做批量操作:具體操作見上
    • 及時關(guān)閉Cursor,避免內(nèi)存泄漏
    • 耗時操作異步化:數(shù)據(jù)庫的操作屬于本地IO,通常比較耗時,建議將這些耗時操作放入異步線程中處理
    • ContentValues的容量調(diào)整:ContentValues內(nèi)部采用HashMap來存儲Key-Value數(shù)據(jù),ContentValues初始容量為8,擴容時翻倍。因此建議對ContentValues填入的內(nèi)容進行估量,設(shè)置合理的初始化容量,減少不必要的內(nèi)部擴容操作
    • 使用索引加快檢索速度:對于查詢操作量級較大、業(yè)務(wù)對要求查詢要求較高的推薦使用索引

IPC相關(guān)

Q:Android中進程和線程的關(guān)系?

  • 技術(shù)點:進程、線程
  • 參考回答:
    • 形象理解:如果把安卓系統(tǒng)比喻成一片土壤,可以把App看做扎根在這片土壤上的工廠,每個APP一般對應(yīng)一個進程,那么線程就像是工廠的生產(chǎn)線。其中,主線程好比是主生產(chǎn)線,只有一條,子線程就像是副生產(chǎn)線,可以有很多條。
    • 關(guān)系:一個APP一般對應(yīng)一個進程和有限個線程
      • 一般對應(yīng)一個進程,當(dāng)然,可以在AndroidMenifest中給四大組件指定屬性android:process開啟多進程模式
      • 有限個線程:線程是一種受限的系統(tǒng)資源,不可無限制的產(chǎn)生且線程的創(chuàng)建和銷毀都有一定的開銷。

Q:為何需要進行IPC?多進程通信可能會出現(xiàn)什么問題?

  • 技術(shù)點:多進程通信
  • 思路:討論多進程通信會出現(xiàn)的問題得出IPC的必要性
  • 參考回答:
  • (1)多進程造成的影響可總結(jié)為以下四方面:
    • 靜態(tài)變量和單例模式失效:由獨立的虛擬機造成
    • 線程同步機制失效:由獨立的虛擬機造成
    • SharedPreference的不可靠下降:不支持兩個進程同時進行讀寫操作,即不支持并發(fā)讀寫,有一定幾率導(dǎo)致數(shù)據(jù)丟失
    • Application多次創(chuàng)建: Android系統(tǒng)會為新的進程分配獨立虛擬機,相當(dāng)于系統(tǒng)又把這個應(yīng)用重新啟動了一次。
  • (2)需要進程間通信的必要性:所有運行在不同進程的四大組件,只要它們之間需要通過內(nèi)存在共享數(shù)據(jù),都會共享失敗。這是由于Android為每個應(yīng)用分配了獨立的虛擬機,不同的虛擬機在內(nèi)存分配上有不同的地址空間,這會導(dǎo)致在不同的虛擬機中訪問同一個類的對象會產(chǎn)生多份副本。
  • 引申: 談?wù)処PC的使用場景

Q:什么是序列化?Serializable接口和Parcelable接口的區(qū)別?為何推薦使用后者?

  • 技術(shù)點:序列化
  • 參考回答:序列化表示將一個對象轉(zhuǎn)換成可存儲或可傳輸?shù)臓顟B(tài)。序列化后的對象可以在網(wǎng)絡(luò)上進行傳輸,也可以存儲到本地。
    • 應(yīng)用場景:需要通過Intent和Binder等傳輸類對象就必須完成對象的序列化過程。
    • 兩種方式:實現(xiàn)Serializable/Parcelable接口。不同點如圖:


      Serializable與Parcelable圖解

Q:Android中為何新增Binder來作為主要的IPC方式?

  • 技術(shù)點:Binder機制
  • 思路:回答B(yǎng)inder優(yōu)點
  • 參考回答:Binder機制有什么幾條優(yōu)點:
    • 傳輸效率高、可操作性強:傳輸效率主要影響因素是內(nèi)存拷貝的次數(shù),拷貝次數(shù)越少,傳輸速率越高。從Android進程架構(gòu)角度分析:對于消息隊列、Socket和管道來說,數(shù)據(jù)先從發(fā)送方的緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中,再從內(nèi)核緩存區(qū)拷貝到接收方的緩存區(qū),一共兩次拷貝,如圖:



      而對于Binder來說,數(shù)據(jù)從發(fā)送方的緩存區(qū)拷貝到內(nèi)核的緩存區(qū),而接收方的緩存區(qū)與內(nèi)核的緩存區(qū)是映射到同一塊物理地址的,節(jié)省了一次數(shù)據(jù)拷貝的過程,如圖:



      由于共享內(nèi)存操作復(fù)雜,綜合來看,Binder的傳輸效率是最好的。
    • 實現(xiàn)C/S架構(gòu)方便:Linux的眾IPC方式除了Socket以外都不是基于C/S架構(gòu),而Socket主要用于網(wǎng)絡(luò)間的通信且傳輸效率較低。Binder基于C/S架構(gòu) ,Server端與Client端相對獨立,穩(wěn)定性較好。
    • 安全性高:傳統(tǒng)Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;而Binder機制為每個進程分配了UID/PID且在Binder通信時會根據(jù)UID/PID進行有效性檢測。

Q:使用Binder進行數(shù)據(jù)傳輸?shù)木唧w過程?

  • 技術(shù)點:Binder機制
  • 思路:通過AIDL實現(xiàn)方式解釋Binder數(shù)據(jù)傳輸?shù)木唧w過程
  • 參考回答:服務(wù)端中的Service給與其綁定的客戶端提供Binder對象,客戶端通過AIDL接口中的asInterface()將這個Binder對象轉(zhuǎn)換為代理Proxy,并通過它發(fā)起RPC請求。客戶端發(fā)起請求時會掛起當(dāng)前線程,并將參數(shù)寫入data然后調(diào)用transact(),RPC請求會通過系統(tǒng)底層封裝后由服務(wù)端的onTransact()處理,并將結(jié)果寫入reply,最后返回調(diào)用結(jié)果并喚醒客戶端線程。


Q:Binder框架中ServiceManager的作用?

  • 技術(shù)點:Binder機制
  • 思路:從Binder框架出發(fā)討論每個元素的作用
  • 參考回答:在Binder框架定義了四個角色:Server,Client,ServiceManager和Binder驅(qū)動。其中Server、Client、ServiceManager運行于用戶空間,Binder驅(qū)動運行于內(nèi)核空間。關(guān)系如圖:


    • Server&Client:服務(wù)器&客戶端。在Binder驅(qū)動和Service Manager提供的基礎(chǔ)設(shè)施上,進行Client-Server之間的通信。
    • ServiceManager服務(wù)的管理者,將Binder名字轉(zhuǎn)換為Client中對該Binder的引用,使得Client可以通過Binder名字獲得Server中Binder實體的引用。流程如圖:


  • Binder驅(qū)動:
    • 與硬件設(shè)備沒有關(guān)系,其工作方式與設(shè)備驅(qū)動程序是一樣的,工作于內(nèi)核態(tài)。
    • 提供open()、mmap()、poll()、ioctl() 等標準文件操作。
    • 以字符驅(qū)動設(shè)備中的misc設(shè)備注冊在設(shè)備目錄/dev下,用戶通過/dev/binder訪問該它。
    • 負責(zé)進程之間binder通信的建立,傳遞,計數(shù)管理以及數(shù)據(jù)的傳遞交互等底層支持。
    • 驅(qū)動和應(yīng)用程序之間定義了一套接口協(xié)議,主要功能由ioctl() 接口實現(xiàn),由于ioctl()靈活、方便且能夠一次調(diào)用實現(xiàn)先寫后讀以滿足同步交互,因此不必分別調(diào)用write()和read()接口。
    • 其代碼位于linux目錄的drivers/misc/binder.c中。

Q:Android中有哪些基于Binder的IPC方式?簡單對比下?

  • 技術(shù)點:IPC方式
  • 思路:分析每種IPC方式的優(yōu)缺點和使用場景的差異
  • 參考回答:


    image.png

Q:是否了解AIDL?原理是什么?如何優(yōu)化多模塊都使用AIDL的情況?

  • 技術(shù)點:AIDL
  • 思路:
  • 參考回答:
    • AIDL(Android Interface Definition Language,Android接口定義語言):如果在一個進程中要調(diào)用另一個進程中對象的方法,可使用AIDL生成可序列化的參數(shù),AIDL會生成一個服務(wù)端對象的代理類,通過它客戶端實現(xiàn)間接調(diào)用服務(wù)端對象的方法。
    • AIDL的本質(zhì)是系統(tǒng)提供了一套可快速實現(xiàn)Binder的工具。關(guān)鍵類和方法:
      • AIDL接口:繼承Interface。
      • Stub類:Binder的實現(xiàn)類,服務(wù)端通過這個類來提供服務(wù)。
      • Proxy類:服務(wù)器的本地代理,客戶端通過這個類調(diào)用服務(wù)器的方法。
      • asInterface():客戶端調(diào)用,將服務(wù)端的返回的Binder對象,轉(zhuǎn)換成客戶端所需要的AIDL接口類型對象。返回對象:
        • 若客戶端和服務(wù)端位于同一進程,則直接返回Stub對象本身;
        • 否則,返回的是系統(tǒng)封裝后的Stub.proxy對象。
      • asBinder():根據(jù)當(dāng)前調(diào)用情況返回代理Proxy的Binder對象。
      • onTransact():運行服務(wù)端的Binder線程池中,當(dāng)客戶端發(fā)起跨進程請求時,遠程請求會通過系統(tǒng)底層封裝后交由此方法來處理。
      • transact():運行在客戶端,當(dāng)客戶端發(fā)起遠程請求的同時將當(dāng)前線程掛起。之后調(diào)用服務(wù)端的onTransact()直到遠程請求返回,當(dāng)前線程才繼續(xù)執(zhí)行。
    • 當(dāng)有多個業(yè)務(wù)模塊都需要AIDL來進行IPC,此時需要為每個模塊創(chuàng)建特定的aidl文件,那么相應(yīng)的Service就會很多。必然會出現(xiàn)系統(tǒng)資源耗費嚴重、應(yīng)用過度重量級的問題。解決辦法是建立Binder連接池,即將每個業(yè)務(wù)模塊的Binder請求統(tǒng)一轉(zhuǎn)發(fā)到一個遠程Service中去執(zhí)行,從而避免重復(fù)創(chuàng)建Service。
    • 工作原理:每個業(yè)務(wù)模塊創(chuàng)建自己的AIDL接口并實現(xiàn)此接口,然后向服務(wù)端提供自己的唯一標識和其對應(yīng)的Binder對象。服務(wù)端只需要一個Service,服務(wù)器提供一個queryBinder接口,它會根據(jù)業(yè)務(wù)模塊的特征來返回相應(yīng)的Binder對像,不同的業(yè)務(wù)模塊拿到所需的Binder對象后就可進行遠程方法的調(diào)用了。流程如圖:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容