android socket_附详尽答案,新版精选Android中高级面试题二
碼個蛋(codeegg) 第 911?次推文
作者:Focusing
鏈接:https://juejin.im/post/5c8211fee51d453a136e36b0
數據存儲
1、描述一下Android數據持久存儲方式?
參考回答:Android平臺實現數據持久存儲的常見幾種方式:
SharedPreferences存儲:一種輕型的數據存儲方式,本質是基于XML文件存儲的key-value鍵值對數據,通常用來存儲一些簡單的配置信息(如應用程序的各種配置信息);
SQLite數據庫存儲:一種輕量級嵌入式數據庫引擎,它的運算速度非常快,占用資源很少,常用來存儲大量復雜的關系數據;
ContentProvider:四大組件之一,用于數據的存儲和共享,不僅可以讓不同應用程序之間進行數據共享,還可以選擇只對哪一部分數據進行共享,可保證程序中的隱私數據不會有泄漏風險;
File文件存儲:寫入和讀取文件的方法和 Java中實現I/O的程序一樣;
網絡存儲:主要在遠程的服務器中存儲相關數據,用戶操作的相關數據可以同步到服務器上;
2、SharedPreferences的應用場景?注意事項?
參考回答:SharedPreferences是一種輕型的數據存儲方式,本質是基于XML文件存儲的key-value鍵值對數據,通常用來存儲一些簡單的配置信息,如int,String,boolean、float和long;
注意事項:
勿存儲大型復雜數據,這會引起內存GC、阻塞主線程使頁面卡頓產生ANR
勿在多進程模式下,操作Sp
不要多次edit和apply,盡量批量修改一次提交
建議apply,少用commit
推薦文章:
史上最全面,清晰的SharedPreferences解析(https://blog.csdn.net/geekerhw/article/details/79713068)
SharedPreferences在多進程中的使用及注意事項(http://zmywly8866.github.io/2015/09/09/sharedpreferences-in-multiprocess.html)
3、SharedPrefrences的apply和commit有什么區別?
參考回答:apply沒有返回值而commit返回boolean表明修改是否提交成功。
apply是將修改數據原子提交到內存, 而后異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤,因此,在多個并發的提交commit的時候,他們會等待正在處理的commit保存到磁盤后在操作,從而降低了效率。而apply只是原子的提交到內容,后面有調用apply的函數的將會直接覆蓋前面的內存數據,這樣從一定程度上提高了很多效率。
apply方法不會提示任何失敗的提示。由于在一個進程中,sharedPreference是單實例,一般不會出現并發沖突,如果對提交的結果不關心的話,建議使用apply,當然需要確保提交成功且有后續操作的話,還是需要用commit的。
4、了解SQLite中的事務操作嗎?是如何做的
參考回答:SQLite在做CRDU操作時都默認開啟了事務,然后把SQL語句翻譯成對應的SQLiteStatement并調用其相應的CRUD方法,此時整個操作還是在rollback journal這個臨時文件上進行,只有操作順利完成才會更新db數據庫,否則會被回滾;
5、使用SQLite做批量操作有什么好的方法嗎?
參考回答:使用SQLiteDatabase的beginTransaction方法開啟一個事務,將批量操作SQL語句轉化為SQLiteStatement并進行批量操作,結束后endTransaction()
6、如何刪除SQLite中表的個別字段
參考回答:SQLite數據庫只允許增加字段而不允許修改和刪除表字段,只能創建新表保留原有字段,刪除原表
7、使用SQLite時會有哪些優化操作?
使用事務做批量操作
及時關閉Cursor,避免內存泄露
耗時操作異步化:數據庫的操作屬于本地IO耗時操作,建議放入異步線程中處理
ContentValues的容量調整:ContentValues內部采用HashMap來存儲Key-Value數據,ContentValues初始容量為8,擴容時翻倍。因此建議對ContentValues填入的內容進行估量,設置合理的初始化容量,減少不必要的內部擴容操作
使用索引加快檢索速度:對于查詢操作量級較大、業務對查詢要求較高的推薦使用索引
IPC
1、Android中進程和線程的關系?區別?
線程是CPU調度的最小單元,同時線程是一種有限的系統資源
進程一般指一個執行單元,在PC和移動設備上一個程序或者一個應用
一般來說,一個App程序至少有一個進程,一個進程至少有一個線程(包含與被包含的關系),
通俗來講就是,在App這個工廠里面有一個進程,線程就是里面的生產線,但主線程(主生產線)只有一條,而子線程(副生產線)可以有多個
進程有自己獨立的地址空間,而進程中的線程共享此地址空間,都可以并發執行
推薦文章:Android developer官方文檔--進程和線程(https://developer.android.com/guide/components/processes-and-threads?hl=zh-cn)
2、如何開啟多進程 ?應用是否可以開啟N個進程 ?
在AndroidMenifest中給四大組件指定屬性android:process開啟多進程模式
在內存允許的條件下可以開啟N個進程
推薦講解:如何開啟多進程?應用是否可以開啟N個進程?(https://github.com/qmsggg/qmsggg_BlogCollect/issues/158)
3、為何需要IPC?多進程通信可能會出現的問題?
參考回答:所有運行在不同進程的四大組件(Activity、Service、Receiver、ContentProvider)共享數據都會失敗,這是由于Android為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。比如常用例子(通過開啟多進程獲取更大內存空間、兩個或者多個應用之間共享數據、微信全家桶)
一般來說,使用多進程通信會造成如下幾方面的問題:
靜態成員和單例模式完全失效:獨立的虛擬機造成
線程同步機制完全實效:獨立的虛擬機造成
SharedPreferences的可靠性下降:這是因為Sp不支持兩個進程并發進行讀寫,有一定幾率導致數據丟失
Application會多次創建:Android系統在創建新的進程會分配獨立的虛擬機,所以這個過程其實就是啟動一個應用的過程,自然也會創建新的Application
推薦文章:Android developer官方文檔--進程和線程(https://developer.android.com/guide/components/processes-and-threads?hl=zh-cn)
4、Android中IPC方式、各種方式優缺點,為什么選擇Binder?
參考回答:
與Linux上傳統的IPC機制,比如System V,Socket相比,Binder好在哪呢?
傳輸效率高、可操作性強:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從Android進程架構角度分析:對于消息隊列、Socket和管道來說,數據先從發送方的緩存區拷貝到內核開辟的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝,如圖:
而對于Binder來說,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程,如圖:
由于共享內存操作復雜,綜合來看,Binder的傳輸效率是最好的。
實現C/S架構方便:Linux的IPC方式除了Socket以外都不是基于C/S架構,而Socket主要用于網絡間的通信且傳輸效率較低。Binder基于C/S架構 ,Server端與Client端相對獨立,穩定性較好。
安全性高:傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;而Binder機制為每個進程分配了UID/PID且在Binder通信時會根據UID/PID進行有效性檢測。
推薦文章:為什么 Android 要采用 Binder 作為 IPC 機制?(https://www.zhihu.com/question/39440766)
5、Binder機制的作用和原理?
參考回答:Linux系統將一個進程分為用戶空間和內核空間。對于進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,為了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即Android的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式。
一次完整的 Binder IPC 通信過程通常是這樣:
首先 Binder 驅動在內核空間創建一個數據接收緩存區;
接著在內核空間開辟一塊內核緩存區,建立內核緩存區和內核中數據接收緩存區之間的映射關系,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關系;
發送方進程通過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,由于內核緩存區和接收進程的用戶空間存在內存映射,因此也就相當于把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。
6、Binder框架中ServiceManager的作用?
參考回答:Binder框架 是基于 C/S 架構的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder驅動,其中 Client、Server、Service Manager 運行在用戶空間,Binder 驅動運行在內核空間
Server&Client:服務器&客戶端。在Binder驅動和Service Manager提供的基礎設施上,進行Client-Server之間的通信。
ServiceManager(如同DNS域名服務器)服務的管理者,將Binder名字轉換為Client中對該Binder的引用,使得Client可以通過Binder名字獲得Server中Binder實體的引用。
Binder驅動(如同路由器):負責進程之間binder通信的建立,傳遞,計數管理以及數據的傳遞交互等底層支持。
圖片出自Carson_Ho文章 —— Android跨進程通信:圖文詳解 Binder機制 原理
7、Bundle傳遞對象為什么需要序列化?Serialzable和Parcelable的區別?
參考回答:因為bundle傳遞數據時只支持基本數據類型,所以在傳遞對象時需要序列化轉換成可存儲或可傳輸的本質狀態(字節流)。序列化后的對象可以在網絡、IPC(比如啟動另一個進程的Activity、Service和Reciver)之間進行傳輸,也可以存儲到本地。
序列化實現的兩種方式:實現Serializable/Parcelable接口。不同點如圖:
8、講講AIDL?原理是什么?如何優化多模塊都使用AIDL的情況?
參考回答:AIDL(Android Interface Definition Language,Android接口定義語言):如果在一個進程中要調用另一個進程中對象的方法,可使用AIDL生成可序列化的參數,AIDL會生成一個服務端對象的代理類,通過它客戶端實現間接調用服務端對象的方法。
AIDL的本質是系統提供了一套可快速實現Binder的工具。關鍵類和方法:
AIDL接口:繼承IInterface。
Stub類:Binder的實現類,服務端通過這個類來提供服務。
Proxy類:服務器的本地代理,客戶端通過這個類調用服務器的方法。
asInterface():客戶端調用,將服務端的返回的Binder對象,轉換成客戶端所需要的AIDL接口類型對象。如果客戶端和服務端位于統一進程,則直接返回Stub對象本身,否則返回系統封裝后的Stub.proxy對象
asBinder():根據當前調用情況返回代理Proxy的Binder對象。
onTransact():運行服務端的Binder線程池中,當客戶端發起跨進程請求時,遠程請求會通過系統底層封裝后交由此方法來處理。
transact():運行在客戶端,當客戶端發起遠程請求的同時將當前線程掛起。之后調用服務端的onTransact()直到遠程請求返回,當前線程才繼續執行。
當有多個業務模塊都需要AIDL來進行IPC,此時需要為每個模塊創建特定的aidl文件,那么相應的Service就會很多。必然會出現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立Binder連接池,即將每個業務模塊的Binder請求統一轉發到一個遠程Service中去執行,從而避免重復創建Service。
工作原理:每個業務模塊創建自己的AIDL接口并實現此接口,然后向服務端提供自己的唯一標識和其對應的Binder對象。服務端只需要一個Service,服務器提供一個queryBinder接口,它會根據業務模塊的特征來返回相應的Binder對象,不同的業務模塊拿到所需的Binder對象后就可進行遠程方法的調用了
View
1、講下View的繪制流程?
參考回答:View的工作流程主要是指measure、layout、draw這三大流程,即測量、布局和繪制,其中measure確定View的測量寬/高,layout確定View的最終寬/高和四個頂點的位置,而draw則將View繪制到屏幕上
View的繪制過程遵循如下幾步:
繪制背景 background.draw(canvas)
繪制自己(onDraw)
繪制 children(dispatchDraw)
繪制裝飾(onDrawScollBars)
推薦文章:
官方文檔(https://developer.android.com/reference/android/view/View)
Android View的繪制流程(https://www.jianshu.com/p/5a71014e7b1b)
Android應用層View繪制流程與源碼分析(https://blog.csdn.net/yanbober/article/details/46128379)
2、MotionEvent是什么?包含幾種事件?什么條件下會產生?
參考回答:MotionEvent是手指接觸屏幕后所產生的一系列事件。典型的事件類型有如下:
ACTION_DOWN:手指剛接觸屏幕
ACTION_MOVE:手指在屏幕上移動
ACTION_UP:手指從屏幕上松開的一瞬間
ACTION_CANCELL:手指保持按下操作,并從當前控件轉移到外層控件時觸發
正常情況下,一次手指觸摸屏幕的行為會觸發一系列點擊事件,考慮如下幾種情況:
點擊屏幕后松開,事件序列:DOWN→UP
點擊屏幕滑動一會再松開,事件序列為DOWN→MOVE→.....→MOVE→UP
3、描述一下View事件傳遞分發機制?
參考回答:View事件分發本質就是對MotionEvent事件分發的過程。即當一個MotionEvent發生后,系統將這個點擊事件傳遞到一個具體的View上
點擊事件的傳遞順序:Activity(Window)→ViewGroup→ View
事件分發過程由三個方法共同完成:
dispatchTouchEvent:用來進行事件的分發。如果事件能夠傳遞給當前View,那么此方法一定會被調用,返回結果受當前View的onTouchEvent和下級View的dispatchTouchEvent方法的影響,表示是否消耗當前事件
onInterceptTouchEvent:在上述方法內部調用,對事件進行攔截。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的。一旦攔截,則執行ViewGroup的onTouchEvent,在ViewGroup中處理事件,而不接著分發給View。且只調用一次,返回結果表示是否攔截當前事件
onTouchEvent:在dispatchTouchEvent方法中調用,用來處理點擊事件,返回結果表示是否消耗當前事件
4、如何解決View的事件沖突 ?舉個開發中遇到的例子 ?
參考回答:常見開發中事件沖突的有ScrollView與RecyclerView的滑動沖突、RecyclerView內嵌同時滑動同一方向
滑動沖突的處理規則:
對于由于外部滑動和內部滑動方向不一致導致的滑動沖突,可以根據滑動的方向判斷誰來攔截事件。
對于由于外部滑動方向和內部滑動方向一致導致的滑動沖突,可以根據業務需求,規定何時讓外部View攔截事件,何時由內部View攔截事件。
對于上面兩種情況的嵌套,相對復雜,可同樣根據需求在業務上找到突破點。
滑動沖突的實現方法:
外部攔截法:指點擊事件都先經過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截。具體方法:需要重寫父容器的onInterceptTouchEvent方法,在內部做出相應的攔截。
內部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進行處理。具體方法:需要配合requestDisallowInterceptTouchEvent方法。
5、scrollTo()和scollBy()的區別?
參考回答:
scollBy內部調用了scrollTo,它是基于當前位置的相對滑動;而scrollTo是絕對滑動,因此如果使用相同輸入參數多次調用scrollTo方法,由于View的初始位置是不變的,所以只會出現一次View滾動的效果
兩者都只能對View內容的滑動,而非使View本身滑動。可以使用Scroller有過度滑動的效果
推薦文章:View 的滑動原理和實現方式(https://www.jianshu.com/p/a177869b0382)
6、Scroller是怎么實現View的彈性滑動?
參考回答:
在MotionEvent.ACTION_UP事件觸發時調用startScroll()方法,該方法并沒有進行實際的滑動操作,而是記錄滑動相關量(滑動距離、滑動時間)
接著調用invalidate/postInvalidate()方法,請求View重繪,導致View.draw方法被執行
當View重繪后會在draw方法中調用computeScroll方法,而computeScroll又會去向Scroller獲取當前的scrollX和scrollY;然后通過scrollTo方法實現滑動;接著又調用postInvalidate方法來進行第二次重繪,和之前流程一樣,如此反復導致View不斷進行小幅度的滑動,而多次的小幅度滑動就組成了彈性滑動,直到整個滑動過程結束
7、 invalidate()和postInvalidate()的區別 ?
參考回答:invalidate()與postInvalidate()都用于刷新View,主要區別是invalidate()在主線程中調用,若在子線程中使用需要配合handler;而postInvalidate()可在子線程中直接調用。
8、SurfaceView和View的區別?
View需要在UI線程對畫面進行刷新,而SurfaceView可在子線程進行頁面的刷新
View適用于主動更新的情況,而SurfaceView適用于被動更新,如頻繁刷新,這是因為如果使用View頻繁刷新會阻塞主線程,導致界面卡頓
SurfaceView在底層已實現雙緩沖機制,而View沒有,因此SurfaceView更適用于需要頻繁刷新、刷新時數據處理量很大的頁面(如視頻播放界面)
9、自定義View如何考慮機型適配 ?
合理使用warp_content,match_parent
盡可能的是使用RelativeLayout
針對不同的機型,使用不同的布局文件放在對應的目錄下,android會自動匹配。
盡量使用點9圖片。
使用與密度無關的像素單位dp,sp
引入android的百分比布局。
切圖的時候切大分辨率的圖,應用到布局當中。在小分辨率的手機上也會有很好的顯示效果。
相關文章:
面試中不要說這些“自殺”的話
如何在面試中介紹自己的項目經驗,90%的人都做錯了!
不得不知的40個知乎高贊問答!
今日問題:
今天最令你,印象深刻的是哪一題?
專屬升級社區:《這件事情,我終于想明白了》?
總結
以上是生活随笔為你收集整理的android socket_附详尽答案,新版精选Android中高级面试题二的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ae万能弹性表达式_外置常用ae插件
- 下一篇: servlet指定时间到现在过了多久_就