1.面試題解
前言:
過去的這一個月,忙過了爆炸開學周、結束了推免、和朋友出門閒遊放鬆了幾天、回家休息慶祝了中秋節國慶節,最後才是這篇姍姍來遲的題解,請原諒我的懶吧!題解乃見仁見智之事,以下只是自己的看法,僅供參考,因本人水平有限,如有問題歡迎指正。之所以是題解1.0,是希望隨著學習的深入,以後能更深刻的理解,在出個題解2.0最好不過了。
1.1 Android
- Activity
Q:說下Activity的生命週期?
技術點:Activity生命週期思路:分條解釋Activity從創建到銷燬整個生命週期中涉及到的方法及作用參考回答:在Activity的生命週期涉及到七大方法,分別是:onCreate()表示Activity 正在創建,常做初始化工作,如setContentView界面資源、初始化數據onStart()表示Activity 正在啟動,這時Activity 可見但不在前臺,無法和用戶交互onResume()表示Activity 獲得焦點,此時Activity 可見且在前臺並開始活動onPause()表示Activity 正在停止,可做 數據存儲、停止動畫等操作onStop()表示activity 即將停止,可做稍微重量級回收工作,如取消網絡連接、註銷廣播接收器等onDestroy()表示Activity
即將銷燬,常做回收工作、資源釋放另外,當Activity由後臺切換到前臺,由不可見到可見時或調用onRestart(),表示Activity 重新啟動Q:onStart()和onResume()/onPause()和onStop()的區別?
技術點:Activity生命週期思路:可從使用細節出發參考回答:onStart()與onStop()是從Activity是否可見這個角度調用的,onResume()和onPause()是從Activity是否顯示在前臺這個角度來回調的,在實際使用沒其他明顯區別。
Q:Activity A啟動另一個Activity B會回調哪些方法?如果Activity B是完全透明呢?如果啟動的是一個對話框Activity呢?
技術點:Activity生命週期參考回答:Activity A啟動另一個Activity B會回調的方法:Activity A的onPause() -->Activity B的onCreate()-->onStart()-->onResume()-->Activity A的onStop();如果Activity B是完全透明的,則最後不會調用Activity A的onStop();如果是對話框Activity,同後種情況。
Q:談談onSaveInstanceState()方法?何時會調用?
技術點:Activity重建思路:可從使用場景、調用次序上解釋參考回答:當非人為終止Activity時,比如系統配置發生改變時導致Activity被殺死並重新創建、資源內存不足導致低優先級的Activity被殺死,會調用 onSavaInstanceState() 來保存狀態。該方法調用在onStop之前,但和onPause沒有時序關係。引申:可再談談它和onRestoreInstanceState()的關係以及後者的作用
Q:onSaveInstanceState()與onPause()的區別?
技術點:Activity重建思路:可從適用場景出發參考回答:onSaveInstanceState()適用於對臨時性狀態的保存,而onPause()適用於對數據的持久化保存。
Q:如何避免配置改變時Activity重建?
技術點:Activity重建思路:一種解決思路是設置配置文件中Activity的configChanges屬性參考回答:為了避免由於配置改變導致Activity重建,可在AndroidManifest.xml中對應的Activity中設置android:configChanges="orientation|screenSize"。此時再次旋轉屏幕時,該Activity不會被系統殺死和重建,只會調用onConfigurationChanged。因此,當配置程序需要響應配置改變,指定configChanges屬性,重寫onConfigurationChanged方法即可。
Q:優先級低的Activity在內存不足被回收後怎樣做可以恢復到銷燬前狀態?
技術點:Activity重建思路:可從Activity重建會被調用的方法出發參考回答:優先級低的Activity在內存不足被回收後重新打開會引發Activity重建。Activity被重新創建時會調用onRestoreInstanceState(該方法在onStart之後),並將onSavaInstanceState保存的
Bundle對象作為參數傳到onRestoreInstanceState與onCreate方法。因此可通過onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)來判斷Activity是否被重建,並取出數據進行恢復。但需要注意的是,在onCreate取出數據時一定要先判斷savedInstanceState是否為空。另外,谷歌更推薦使用onRestoreInstanceState進行數據恢復。Q:說下Activity的四種啟動模式?(有時會出個實際問題來分析返回棧中Activity的情況)
技術點:Activity啟動模式思路:分條解釋四個啟動模式的特點參考回答:standard標準模式:每次啟動一個Activity就會創建一個新的實例singleTop棧頂複用模式:如果新Activity已經位於任務棧的棧頂,就不會重新創建,並回調 onNewIntent(intent) 方法singleTask棧內複用模式:只要該Activity在一個任務棧中存在,都不會重新創建,並回調 onNewIntent(intent) 方法。如果不存在,系統會先尋找是否存在需要的棧,如果不存在該棧,就創建一個任務棧,並把該Activity放進去;如果存在,就會創建到已經存在的棧中singleInstance單實例模式:具有此模式的Activity只能單獨位於一個任務棧中,且此任務棧中只有唯一一個實例
Q:談談singleTop和singleTask的區別以及應用場景
技術點:Activity啟動模式思路:可先解釋兩個啟動模式的含義(見上一個問題),再總結不同點,最後給出應用實例參考回答:singleTop和singleTask的含義分別是......,可見兩者大致區別有:singleTop:同個Activity實例在棧中可以有多個,即可能重複創建;該模式的Activity會默認進入啟動它所屬的任務棧,即不會引起任務棧的變更;為防止快速點擊時多次startActivity,可以將目標Activity設置為singleTopsingleTask:同個Activity實例在棧中只有一個,即不存在重複創建;可通過android:taskAffinity設定該Activity需要的任務棧,即可能會引起任務棧的變更;常用於主頁和登陸頁
Q:onNewIntent()調用時機?
技術點:Activity啟動模式參考回答:啟動模式為singleTop或singleTask的Activity在以下情況會回調onNewIntent():singleTop:如果新Activity已經位於任務棧的棧頂,就不會重新創建,並回調 onNewIntent(intent) 方法singleTask:只要該Activity在一個任務棧中存在,都不會重新創建,並回調 onNewIntent(intent) 方法
Q:瞭解哪些Activity啟動模式的標記位?
技術點:Activity啟動模式參考回答:常見的兩個標記為:FLAG_ACTIVITY_SINGLE_TOP:對應singleTop啟動模式FLAG_ACTIVITY_NEW_TASK :對應singleTask模式引申:可再談談singleTop和singleTask具體效果
Q:如何啟動其他應用的Activity?
技術點:Activity啟動、IntentFilter匹配思路:可從隱式Intent角度出發參考回答:在保證有權限訪問的情況下,通過隱式Intent進行目標Activity的IntentFilter匹配,原則是:一個intent只有同時匹配某個Activity的intent-filter中的action、category、data才算完全匹配,才能啟動該Activity。一個Activity可以有多個 intent-filter,一個 intent只要成功匹配
任意一組 intent-filter,就可以啟動該Activity。引申:如有必要可展開說明action、category、data的具體匹配規則Q:Activity的啟動過程?
技術點:Activity啟動、ActivityManagerServie、ApplicationThread思路:可大致介紹Activity啟動過程涉及到的類,尤其是ActivityManagerServie、ApplicationThread從中發揮的作用。詳見要點提煉|開發藝術之四大組件參考回答:調用startActivity()後經過重重方法會轉移到ActivityManagerService的startActivity(),並通過一個IPC回到ActivityThread的內部類ApplicationThread中,並調用其scheduleLaunchActivity()將啟動Activity的消息發送並交由Handler H處理。Handler H對消息的處理會調用handleLaunchActivity()->performLaunchActivity()得以完成Activity對象的創建和啟動。引申:由於ActivityManagerService是一個Binder對象,可引申談談Binder機制
- Fragment
Q:談一談Fragment的生命週期?
技術點:Fragment生命週期思路:分條解釋Fragment從創建到銷燬整個生命週期中涉及到的方法及作用參考回答:Fragment從創建到銷燬整個生命週期中涉及到的方法依次為:onAttach()->onCreate()-> onCreateView()->onActivityCreated()->onStart()->onResume()->onPause()->onStop()->onDestroyView()->onDestroy()->onDetach(),其中和Activity有不少名稱相同作用相似的方法,而不同的方法有:onAttach():當Fragment和Activity建立關聯時調用onCreateView() :當Fragment創建視圖時調用onActivityCreated():當與Fragment相關聯的Activity完成onCreate()之後調用onDestroyView():在Fragment中的佈局被移除時調用onDetach():當Fragment和Activity解除關聯時調用
Q:Activity和Fragment的異同?
技術點:Fragment作用思路:分別解釋“異”“同”參考回答:Activity和Fragment的相似點在於,它們都可包含佈局、可有自己的生命週期,Fragment可看似迷你活動。不同點是,由於Fragment是依附在Activity上的,多了些和宿主Activity相關的生命週期方法,如onAttach()、onActivityCreated()、onDetach();另外,Fragment的生命週期方法是由宿主Activity而不是操作系統調用的,Activity中生命週期方法都是protected,而Fragment都是public,也能印證了這一點,因為Activity需要調用Fragment那些方法並管理它。引申:可具體談談Activity和Fragment的關係
Q:Activity和Fragment的關係?
技術點:Fragment作用思路:可從Fragment出現的目的、兩者數量關係、調用關係展開參考回答:正如Fragment的名字“碎片”,它的出現是為了解決Android碎片化 ,它可作為Activity界面的組成部分,可在Activity運行中實現動態的加入、移除和交換。一個Activity中可同時出現多個Fragment,一個Fragment也可在多個Activity中使用。另外,Activity的FragmentManager負責調用隊列中Fragment的生命週期方法,只要Fragment的狀態與Activity的狀態保持了同步,宿主Activity的FragmentManager便會繼續調用其他生命週期方法以繼續保持Fragment與Activity的狀態一致。
Q:何時會考慮使用Fragment?
技術點:Fragment作用思路:列舉更適合使用Fragment的情況參考回答:非常經典的例子,即用兩個Fragment封裝兩個界面模塊,這樣只使一套代碼就能適配兩種設備,達到兩種界面效果;單一場景切換時使用Fragment更輕量化,如ViewPager和Fragment搭配使用
- Service
Q:談一談Service的生命週期?
技術點:Service生命週期思路:分條解釋Service從創建到銷燬整個生命週期中涉及到的方法及作用參考回答:在Service的生命週期涉及到六大方法,分別是:onCreate():服務第一次被創建時調用onStartComand():服務啟動時調用onBind():服務被綁定時調用onUnBind():服務被解綁時調用onDestroy():服務停止時調用引申:談談相對應的兩種啟動方式
Q:Service的兩種啟動方式?區別在哪?
技術點:Service生命週期思路:分別解釋兩種啟動模式如何啟動和停止Service,並引起生命週期怎樣的變化參考回答:第一種,其他組件調用Context的 startService() 方法可以啟動一個Service,並回調服務中的onStartCommand()。如果該服務之前還沒創建,那麼回調的順序是onCreate()->onStartCommand()。服務啟動了之後會一直保持運行狀態,直到 stopService() 或 stopSelf() 方法被調用,服務停止並回調onDestroy()。另外,無論調用多少次startService()方法,只需調用一次stopService()或stopSelf()方法,服務就會停止了。第二種,其它組件調用Context的 bindService() 可以綁定一個Service,並回調服務中的onBind()方法。類似地,如果該服務之前還沒創建,那麼回調的順序是onCreate()->onBind()。之後,調用方可以獲取到onBind()方法裡返回的IBinder對象的實例,從而實現和服務進行通信。只要調用方和服務之間的連接沒有斷開,服務就會一直保持運行狀態,直到調用了 unbindService() 方法服務會停止,回調順序onUnBind()->onDestroy()。
Q:一個Activty先start一個Service後,再bind時會回調什麼方法?此時如何做才能回調Service的destory()方法?
技術點:Service生命週期參考回答:startService()啟動Service之後,再bindService()綁定,此時只會回調onBind()方法;若想回調Service的destory()方法,需要同時調用 stopService()和 unbindService()方法才能讓服務銷燬掉。
Q:Service如何和Activity進行通信?
技術點:Service信息傳遞思路:簡單介紹Service如何和Activity雙向通信的流程參考回答:通過bindService()可以實現Activity調用Service中的方法,具體步驟見學習筆記| AS入門(十) 組件篇之Service; 通過廣播實現Service向Activity發送消息引申:談談底層的Binder機制
Q:用過哪些系統Service?
技術點:Service類型(系統Service)參考回答:
Q:是否能在Service進行耗時操作?如果非要可以怎麼做?
技術點:Service使用注意參考回答:Service默認並不會運行在子線程中,也不運行在一個獨立的進程中,它同樣執行在主線程中(UI線程)。換句話說,不要在Service裡執行耗時操作,除非手動打開一個子線程,否則有可能出現主線程被阻塞(ANR)的情況。引申:可以引申談談開子線程的幾種方法
Q:AlarmManager能實現定時的原理?
技術點:系統服務(後臺定時)思路:AlarmManager參考回答:通過調用AlarmManager的 set() 方法就可以設置一個定時任務,並提供三個參數(工作類型,定時任務觸發的時間,PendingIntent對象)。其中第三個PendingIntent對象是關鍵,一般會調用它的
getBroadcast() 方法來獲取一個能夠執行廣播的PendingIntent。這樣當定時任務被觸發的時候,廣播接收器的onReceive()方法就可以得到執行。即通過服務和廣播的循環觸發實現定時服務。引申:可談談底層定時機制實現原理Q:前臺服務是什麼?和普通服務的不同?如何去開啟一個前臺服務?
技術點:Service類型(前臺Service)參考回答:和一般運行在後臺的服務不同,前臺服務的服務狀態可以被用戶一眼看到。它和普通服務最大的區別是,前者會一直有一個正在運行的圖標在系統的狀態欄顯示,下拉狀態欄後可以看到更加詳細的信息,非常類似於通知的效果,且當系統內存不足服務被殺死時,通知會被移除。實現一個前臺服務也非常簡單,和發送一個通知非常類似,只不過在構建好一個Notification之後,不需要NotificationManager將通知顯示出來,而是調用了 startForeground() 方法。
Q:是否瞭解ActivityManagerService,談談它發揮什麼作用?
技術點:Service類型(ActivityManagerService)思路:可談談在四大組件創建中ActivityManagerService發揮的作用,詳見要點提煉|開發藝術之四大組件參考回答:ActivityManagerService是Android中最核心的服務 , 主要負責系統中四大組件的啟動、切換、調度及應用進程的管理和調度等工作,其職責與操作系統中的進程管理和調度模塊類似。引申:看源碼談談AMS啟動過程:ActivityManagerService分析——AMS啟動流程
Q:如何保證Service不被殺死?
技術點:Service應用思路:列舉幾種解決辦法參考回答:可以採取以下幾種解決方法:在Service的onStartCommand()中設置flages值為START_STICKY,使得Service被殺死後嘗試再次啟動Service提升Service優先級,比如設置為一個前臺服務在Activity的onDestroy()通過發送廣播,並在廣播接收器的onReceive()中啟動Service
- Broadcast Receiver
Q:廣播有幾種形式?什麼特點?
技術點:Broadcast類型思路:分條解釋每種廣播類型的特點參考回答:常見以下四種廣播:普通廣播:一種完全異步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播消息,因此它們接收的先後是隨機的。有序廣播:一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播才會繼續傳遞,所以此時的廣播接收器是有先後順序的,且優先級(priority)高的廣播接收器會先收到廣播消息。有序廣播可以被接收器截斷使得後面的接收器無法收到它。本地廣播:發出的廣播只能夠在應用程序的
內部進行傳遞,並且廣播接收器也只能接收本應用程序發出的廣播。粘性廣播:這種廣播會一直滯留,當有匹配該廣播的接收器被註冊後,該接收器就會收到此條廣播。Q:廣播的兩種註冊形式?區別在哪?
技術點:Broadcast使用參考回答:廣播的註冊有兩種方法:一種在活動裡通過代碼動態註冊,另一種在配置文件裡靜態註冊。兩種方式的相同點是都完成了對接收器以及它能接收的廣播值這兩個值的定義;不同點是動態註冊的接收器必須要在程序啟動之後才能接收到廣播,而靜態註冊的接收器即便程序未啟動也能接收到廣播,比如想接收到手機開機完成後系統發出的廣播就只能用靜態註冊了。
- ContentProvider
Q:ContentProvider瞭解多少?
技術點:ContentProvider思路:ContentProvider功能參考回答:作為四大組件之一,ContentProvider主要負責存儲和共享數據。與文件存儲、SharedPreferences存儲、SQLite數據庫存儲這幾種數據存儲方法不同的是,後者保存下的數據只能被該應用程序使用,而前者可以讓不同應用程序之間進行數據共享,它還可以選擇只對哪一部分數據進行共享,從而保證程序中的隱私數據不會有洩漏風險。引申:談談ContentProvider底層使用Binder機制原理
- 數據存儲
Q:Android中提供哪些數據持久存儲的方法?
技術點:數據持久化思路:分條解釋每種數據持久存儲的特點參考回答:Android平臺實現數據存儲的常見幾種方式:File 文件存儲:寫入和讀取文件的方法和 Java中實現I/O的程序一樣。SharedPreferences存儲:一種輕型的數據存儲方式,常用來存儲一些簡單的配置信息,本質是基於XML文件存儲key-value鍵值對數據。SQLite數據庫存儲:一款輕量級的關係型數據庫,它的運算速度非常快,佔用資源很少,在存儲大量複雜的關係型數據的時可以使用。ContentProvider:四大組件之一,用於數據的存儲和共享,不僅可以讓不同應用程序之間進行數據共享,還可以選擇只對哪一部分數據進行共享,可保證程序中的隱私數據不會有洩漏風險。
Q:Java中的I/O流讀寫怎麼做?
技術點:數據持久化(文件存儲)思路:大致介紹核心類和核心方法參考回答:和 Java中實現I/O的程序是一樣的,Context類中提供了openFileInput()和openFileOutput()方法來打開數據文件裡的文件IO流,有關讀寫涉及的主要方法詳見文章學習筆記| AS入門(七) 數據存儲篇
Q:SharePreferences適用情形?使用中需要注意什麼?
技術點:數據持久化(SharePreferences存儲)參考回答:SharePreferences是一種輕型的數據存儲方式,適用於存儲一些簡單的配置信息,如int、string、boolean、float和long。由於系統對SharedPreferences的讀/寫有一定的緩存策略,即在內存中有一份該文件的緩存,因此在多進程模式下,其讀/寫會變得不可靠,甚至丟失數據。引申:談談Android中多進程通信(Binder)
Q:瞭解SQLite中的事務處理嗎?是如何做的?
技術點:數據持久化(SQLite)參考回答:SQLite在做CRDU操作時都默認開啟了事務,然後把SQL語句翻譯成對應的SQLiteStatement並調用其相應的CRUD方法,此時整個操作還是在rollback journal這個臨時文件上進行,只有操作順利完成才會更新.db數據庫,否則會被回滾。引申:談談如何模仿SQLite中事務的思想更高效進行批量操作
Q:使用SQLite做批量操作有什麼好的方法嗎?
技術點:數據持久化(SQLite)思路:模仿SQLite的事務處理參考回答:使用SQLiteDatabase的beginTransaction()方法開啟一個事務,將批量操作SQL語句轉化成SQLiteStatement並進行批量操作,結束後endTransaction()
Q:如果現在要刪除SQLite中表的一個字段如何做?
技術點:數據持久化(SQLite)參考回答:SQLite數據庫只允許增加表字段而不允許修改和刪除表字段,只能採取複製表思想,即創建一個新表保留原表想要的字段、再將原表刪除
Q:使用SQLite時會有哪些優化操作?
技術點:數據持久化(SQLite)思路:列舉可優化點參考回答:使用事務做批量操作:具體操作見上及時關閉Cursor,避免內存洩漏耗時操作異步化:數據庫的操作屬於本地IO,通常比較耗時,建議將這些耗時操作放入異步線程中處理ContentValues的容量調整:ContentValues內部採用HashMap來存儲Key-Value數據,ContentValues初始容量為8,擴容時翻倍。因此建議對ContentValues填入的內容進行估量,設置合理的初始化容量,減少不必要的內部擴容操作使用索引加快檢索速度:對於查詢操作量級較大、業務對要求查詢要求較高的推薦使用索引
- IPC
Q:Android中進程和線程的關係?
技術點:進程、線程參考回答:形象理解:如果把安卓系統比喻成一片土壤,可以把App看做紮根在這片土壤上的工廠,每個APP一般對應一個進程,那麼線程就像是工廠的生產線。其中,主線程好比是主生產線,只有一條,子線程就像是副生產線,可以有很多條。關係:一個APP一般對應一個進程和有限個線程一般對應一個進程,當然,可以在AndroidMenifest中給四大組件指定屬性android:process開啟多進程模式有限個線程:線程是一種
受限的系統資源,不可無限制的產生且線程的創建和銷燬都有一定的開銷。Q:為何需要進行IPC?多進程通信可能會出現什麼問題?
技術點:多進程通信思路:討論多進程通信會出現的問題得出IPC的必要性參考回答:(1)多進程造成的影響可總結為以下四方面:靜態變量和單例模式失效:由獨立的虛擬機造成線程同步機制失效:由獨立的虛擬機造成SharedPreference的不可靠下降:不支持兩個進程同時進行讀寫操作,即不支持併發讀寫,有一定幾率導致數據丟失Application多次創建: Android系統會為新的進程分配獨立虛擬機,相當於系統又把這個應用重新啟動了一次。(2)需要進程間通信的必要性:所有運行在不同進程的四大組件,只要它們之間需要通過內存在共享數據,都會共享失敗。這是由於Android為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。引申: 談談IPC的使用場景
Q:Android中為何新增Binder來作為主要的IPC方式?
技術點:Binder機制思路:回答Binder優點參考回答:Binder機制有什麼幾條優點:傳輸效率高、可操作性強:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從Android進程架構角度分析:對於消息隊列、Socket和管道來說,數據先從發送方的緩存區拷貝到內核開闢的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝,如圖:
而對於Binder來說,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程,如圖:
Q:使用Binder進行數據傳輸的具體過程?
- 技術點:Binder機制
- 思路:通過AIDL實現方式解釋Binder數據傳輸的具體過程
- 參考回答:服務端中的Service給與其綁定的客戶端提供Binder對象,客戶端通過AIDL接口中的asInterface()將這個Binder對象轉換為代理Proxy,並通過它發起RPC請求。客戶端發起請求時會掛起當前線程,並將參數寫入data然後調用transact(),RPC請求會通過系統底層封裝後由服務端的onTransact()處理,並將結果寫入reply,最後返回調用結果並喚醒客戶端線程。
Q:Binder框架中ServiceManager的作用?`
- 技術點:Binder機制
- 思路:從Binder框架出發討論每個元素的作用
- 參考回答:在Binder框架定義了四個角色:Server,Client,ServiceManager和Binder驅動。其中Server、Client、ServiceManager運行於用戶空間,Binder驅動運行於內核空間。關係如圖:
- Server&Client:服務器&客戶端。在Binder驅動和Service Manager提供的基礎設施上,進行Client-Server之間的通信。
- ServiceManager服務的管理者,將Binder名字轉換為Client中對該Binder的引用,使得Client可以通過Binder名字獲得Server中Binder實體的引用。流程如圖:
Binder驅動:與硬件設備沒有關係,其工作方式與設備驅動程序是一樣的,工作於內核態。提供open()、mmap()、poll()、ioctl() 等標準文件操作。以字符驅動設備中的misc設備註冊在設備目錄/dev下,用戶通過/dev/binder訪問該它。負責進程之間binder通信的建立,傳遞,技術管理以及數據的傳遞交互等底層支持。驅動和應用程序之間定義了一套接口協議,主要功能由ioctl() 接口實現,由於ioctl()靈活、方便且能夠一次調用實現先寫後讀以滿足同步交互,因此不必分別調用write()和read()接口。其代碼位於linux目錄的drivers/misc/binder.c中。
Q:Android中有哪些基於Binder的IPC方式?簡單對比下?
- 技術點:IPC方式
- 思路:分析每種IPC方式的優缺點和使用場景的差異
- 參考回答:
Q:MotionEvent是什麼?包含幾種事件?什麼條件下會產生?
技術點:View觸控參考回答:MotionEvent是手指觸摸屏幕所產生的一系列事件。包含的事件有:ACTION_DOWN:手指剛接觸屏幕ACTION_MOVE:手指在屏幕上滑動ACTION_UP:手指在屏幕上鬆開的一瞬間ACTION_CANCEL:手指保持按下操作,並從當前控件轉移到外層控件時會觸發
Q:scrollTo()和scrollBy()的區別?
技術點:View滑動參考回答:scrollBy內部調用了scrollTo,它是基於當前位置的相對滑動;而scrollTo是
絕對滑動,因此如果利用相同輸入參數多次調用scrollTo()方法,由於View初始位置是不變只會出現一次View滾動的效果而不是多次。引申:兩者都只能對view內容進行滑動,而不能使view本身滑動,且非平滑,可使用Scroller有過渡滑動的效果Q:談一談View的事件分發機制?
技術點:View事件分發思路:從分發本質、傳遞順序、核心方法展開參考回答:事件分發本質:就是對MotionEvent事件分發的過程。即當一個MotionEvent產生了以後,系統需要將這個點擊事件傳遞到一個具體的View上。點擊事件的傳遞順序:Activity(Window) -> ViewGroup -> View三個主要方法:dispatchTouchEvent:進行事件的分發(傳遞)。返回值是 boolean 類型,受當前onTouchEvent和下級view的dispatchTouchEvent影響onInterceptTouchEvent:對事件進行攔截。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的。一旦攔截,則執行ViewGroup的onTouchEvent,在ViewGroup中處理事件,而不接著分發給View。且只調用一次,所以後面的事件都會交給ViewGroup處理。onTouchEvent:進行事件處理。
Q:如何解決View的滑動衝突?
技術點:View滑動衝突思路:從處理規則和具體實現方法展開討論參考回答:(1)處理規則:對於由於外部滑動和內部滑動方向不一致導致的滑動衝突,可以根據滑動的方向判斷誰來攔截事件。對於由於外部滑動方向和內部滑動方向一致導致的滑動衝突,可以根據業務需求,規定何時讓外部View攔截事件何時由內部View攔截事件。對於上面兩種情況的嵌套,相對複雜,可同樣根據需求在業務上找到突破點。(2)實現方法:外部攔截法:指點擊事件都先經過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截。具體方法:需要重寫父容器的onInterceptTouchEvent方法,在內部做出相應的攔截。內部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進行處理。具體方法:需要配合requestDisallowInterceptTouchEvent方法。
Q:onTouch()、onTouchEvent()和onClick()關係?
技術點:View事件分發參考回答:優先度onTouch()>onTouchEvent()>onClick()。因此onTouchListener的onTouch()方法會先觸發;如果onTouch()返回false才會接著觸發onTouchEvent(),同樣的,內置諸如onClick()事件的實現等等都基於onTouchEvent();如果onTouch()返回true,這些事件將不會被觸發。引申:OnTouchListener、OnClickListener的衝突
Q:SurfaceView和View的區別?
技術點:View、SurfaceView參考回答:SurfaceView是從View基類中派生出來的顯示類,他和View的區別有:View需要在UI線程對畫面進行刷新,而SurfaceView可在子線程進行頁面的刷新View適用於主動更新的情況,而SurfaceView適用於被動更新,如頻繁刷新,這是因為如果使用View頻繁刷新會阻塞主線程,導致界面卡頓SurfaceView在底層已實現雙緩衝機制,而View沒有,因此SurfaceView更適用於需要頻繁刷新、刷新時數據處理量很大的頁面
Q:invalidate()和postInvalidate()的區別?
技術點:View刷新參考回答:invalidate()與postInvalidate()都用於刷新View,主要區別是invalidate()在主線程中調用,若在子線程中使用需要配合handler;而postInvalidate()可在子線程中直接調用。
- Drawable等資源
Q:瞭解哪些Drawable?適用場景?
技術點:res資源參考回答:BitmapDrawable表示一張圖片、NinePatchDrawable可自動地根據所需的寬/高對圖片進行相應的縮放並保證不失真、ShapeDrawable表示純色、有漸變效果的基礎幾何圖形、StateListDrawable表示一個Drawable的集合且每個Drawable對應著View的一種狀態、LayerDrawable可通過將不同的Drawable放置在不同的層上面從而達到一種疊加後的效果
Q:mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和ldpi存在怎樣的關係?
技術點:res資源參考回答:表示不同密度的圖片資源,像素從高到低依次排序為xxxhdpi>xxhdpi>xhdpi>hdpi>mdpi>ldpi,根據手機的dpi不同加載不同密度的圖片
Q:dp、dpi、px的區別?
技術點:Android適配參考回答:px:像素,如分辨率1920x1080表示高為1920個像素、寬為1080個像素dpi:每英寸的像素點,如分辨率為1920x1080的手機尺寸為4.95英寸,則該手機DPI為(1920x1920+ 1080x1080)½/4.95≈445dpidp:密度無關像素,是個相對值
Q:res目錄和assets目錄的區別?
技術點:res、assets參考回答:res/raw中的文件會被映射到R.java文件中,訪問時可直接使用資源ID,不可以有目錄結構assets文件夾下的文件不會被映射到R.java中,訪問時需要AssetManager類,可以創建的文件夾
由於篇幅原因,還有很多面試題都沒分享出來,這些題目我都已經全部整理成了PDF文件,有需要的朋友們可以
私信我【面試】領取希望可以幫助大家提升進階,也希望最近有面試的朋友們可以找到滿意的工作,拿到高薪進入大廠!