Android篇:2019初中級Android開發社招面試解答(上)

金三銀四,衝擊大廠,你值得擁有的一份2019初中級移動端社招面試總結+解答html

你當前所處:Android篇:2019初中級Android開發社招面試解答(上)android

Android篇:2019初中級Android開發社招面試解答(中)git

Android篇:2019初中級Android開發社招面試解答(下)github

注:由於實際開發與參考答案會有所不一樣,再者怕誤導你們,因此這些面試題答案仍是本身去理解!面試官會針對簡歷中提到的知識點由淺入深提問,因此不要背答案,多理解。面試

Android篇

Activity

一、說下Activity生命週期 ?

  • 參考解答:在正常狀況下,Activity的經常使用生命週期就只有以下7個
    • onCreate():表示Activity正在被建立,經常使用來初始化工做,好比調用setContentView加載界面佈局資源,初始化Activity所需數據等;
    • onRestart():表示Activity正在從新啓動,通常狀況下,當前Acitivty從不可見從新變爲可見時,OnRestart就會被調用;
    • onStart():表示Activity正在被啓動,此時Activity可見但不在前臺,還處於後臺,沒法與用戶交互;
    • onResume():表示Activity得到焦點,此時Activity可見且在前臺並開始活動,這是與onStart的區別所在;
    • onPause():表示Activity正在中止,此時可作一些存儲數據、中止動畫等工做,可是不能太耗時,由於這會影響到新Activity的顯示,onPause必須先執行完,新Activity的onResume纔會執行;
    • onStop():表示Activity即將中止,能夠作一些稍微重量級的回收工做,好比註銷廣播接收器、關閉網絡鏈接等,一樣不能太耗時;
    • onDestroy():表示Activity即將被銷燬,這是Activity生命週期中的最後一個回調,常作回收工做、資源釋放
  • 延伸:從整個生命週期來看,onCreate和onDestroy是配對的,分別標識着Activity的建立和銷燬,而且只可能有一次調用; 從Activity是否可見來講,onStart和onStop是配對的,這兩個方法可能被調用屢次; 從Activity是否在前臺來講,onResume和onPause是配對的,這兩個方法可能被調用屢次; 除了這種區別,在實際使用中沒有其餘明顯區別;

二、Activity A 啓動另外一個Activity B 會調用哪些方法?若是B是透明主題的又或則是個DialogActivity呢 ?

  • 參考解答:Activity A 啓動另外一個Activity B,回調以下
    • Activity A 的onPause() → Activity B的onCreate() → onStart() → onResume() → Activity A的onStop();
    • 若是B是透明主題又或則是個DialogActivity,則不會回調A的onStop;

三、說下onSaveInstanceState()方法的做用 ? 什麼時候會被調用?

  • 參考解答:發生條件:異常狀況下(系統配置發生改變時致使Activity被殺死並從新建立、資源內存不足致使低優先級的Activity被殺死
    • 系統會調用onSaveInstanceState來保存當前Activity的狀態,此方法調用在onStop以前,與onPause沒有既定的時序關係;
    • 當Activity被重建後,系統會調用onRestoreInstanceState,而且把onSave(簡稱)方法所保存的Bundle對象同時傳參給onRestore(簡稱)和onCreate(),所以能夠經過這兩個方法判斷Activity是否被重建,調用在onStart以後;
      異常狀況下Activity的重建過程
  • 推薦文章:

四、說下 Activity的四種啓動模式、應用場景 ?

  • 參考回答:
    • standard標準模式:每次啓動一個Activity都會從新建立一個新的實例,無論這個實例是否已經存在,此模式的Activity默認會進入啓動它的Activity所屬的任務棧中;
    • singleTop棧頂複用模式:若是新Activity已經位於任務棧的棧頂,那麼此Activity不會被從新建立,同時會回調onNewIntent方法,若是新Activity實例已經存在但不在棧頂,那麼Activity依然會被從新建立;
    • singleTask棧內複用模式:只要Activity在一個任務棧中存在,那麼屢次啓動此Activity都不會從新建立實例,並回調onNewIntent方法,此模式啓動Activity A,系統首先會尋找是否存在A想要的任務棧,若是不存在,就會從新建立一個任務棧,而後把建立好A的實例放到棧中;
    • singleInstance單實例模式:這是一種增強的singleTask模式,具備此種模式的Activity只能單獨地位於一個任務棧中,且此任務棧中只有惟一一個實例;
  • 推薦文章:

五、瞭解哪些Activity經常使用的標記位Flags?

  • 參考回答:
    • FLAG_ACTIVITY_NEW_TASK : 對應singleTask啓動模式,其效果和在XML中指定該啓動模式相同;
    • FLAG_ACTIVITY_SINGLE_TOP : 對應singleTop啓動模式,其效果和在XML中指定該啓動模式相同;
    • FLAG_ACTIVITY_CLEAR_TOP : 具備此標記位的Activity,當它啓動時,在同一個任務棧中全部位於它上面的Activity都要出棧。這個標記位通常會和singleTask模式一塊兒出現,在這種狀況下,被啓動Activity的實例若是已經存在,那麼系統就會回調onNewIntent。若是被啓動的Activity採用standard模式啓動,那麼它以及連同它之上的Activity都要出棧,系統會建立新的Activity實例並放入棧中;
    • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS : 具備這個標記的 Activity 不會出如今歷史 Activity 列表中;
  • 推薦文章:

六、說下 Activity跟window,view之間的關係?

  • 參考回答:
    • Activity在建立時會調用 attach() 方法初始化一個PhoneWindow(繼承於Window)每個Activity都包含了惟一一個PhoneWindow
    • Activity經過setContentView其實是調用的 getWindow().setContentView將View設置到PhoneWindow上,而PhoneWindow內部是經過 WindowManageraddViewremoveViewupdateViewLayout這三個方法來管理View,WindowManager本質是接口,最終由WindowManagerImpl實現
  • 延伸
    • WindowManager爲每一個Window建立Surface對象,而後應用就能夠經過這個Surface來繪製任何它想要繪製的東西。而對於WindowManager來講,這只不過是一塊矩形區域而已
      • Surface其實就是一個持有像素點矩陣的對象,這個像素點矩陣是組成顯示在屏幕的圖像的一部分。咱們看到顯示的每一個Window(包括對話框、全屏的Activity、狀態欄等)都有他本身繪製的Surface。而最終的顯示可能存在Window之間遮擋的問題,此時就是經過SurfaceFlinger對象渲染最終的顯示,使他們以正確的Z-order顯示出來。通常Surface擁有一個或多個緩存(通常2個),經過雙緩存來刷新,這樣就能夠一邊繪製一邊加新緩存。
    • ViewWindow裏面用於交互的UI元素。Windowattach一個View Tree(組合模式),當Window須要重繪(如,當View調用invalidate)時,最終轉爲WindowSurfaceSurface被鎖住(locked)並返回Canvas對象,此時View拿到Canvas對象來繪製本身。當全部View繪製完成後,Surface解鎖(unlock),而且post到繪製緩存用於繪製,經過Surface Flinger來組織各個Window,顯示最終的整個屏幕
  • 推薦文章:

七、橫豎屏切換的Activity生命週期變化?

  • 參考回答:
    • 不設置Activity的android:configChanges時,切屏會銷燬當前Activity,而後從新加載調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次; onPause() →onStop()→onDestory()→onCreate()→onStart()→onResume()
    • 設置Activity的android:configChanges="orientation",通過機型測試
      • 在Android5.1 即API 23級別下,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次
      • 在Android9 即API 28級別下,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法
      • 後經官方查正,原話以下
        • 若是您的應用面向Android 3.2即API 級別 13或更高級別(按照 minSdkVersion 和 targetSdkVersion 屬性所聲明的級別),則還應聲明 "screenSize" 配置,由於當設備在橫向與縱向之間切換時,該配置也會發生變化。即使是在 Android 3.2 或更高版本的設備上運行,此配置變動也不會從新啓動 Activity
    • 設置Activity的android:configChanges="orientation|keyboardHidden|screenSize"時,機型測試經過,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法;
  • 推薦文章:

八、如何啓動其餘應用的Activity?

  • 參考回答:
    • 在保證有權限訪問的狀況下,經過隱式Intent進行目標Activity的IntentFilter匹配,原則是:
      • 一個intent只有同時匹配某個Activity的intent-filter中的action、category、data纔算徹底匹配,才能啓動該Activity;
      • 一個Activity能夠有多個 intent-filter,一個 intent只要成功匹配任意一組 intent-filter,就能夠啓動該Activity;
  • 推薦文章:

九、Activity的啓動過程?(重點)

  • 參考回答:
    • 點擊App圖標後經過startActivity遠程調用到AMS中,AMS中將新啓動的activity以activityrecord的結構壓入activity棧中,並經過遠程binder回調到原進程,使得原進程進入pause狀態,原進程pause後通知AMS我pause了
    • 此時AMS再根據棧中Activity的啓動intent中的flag是否含有new_task的標籤判斷是否須要啓動新進程,啓動新進程經過startProcessXXX的函數
    • 啓動新進程後經過反射調用ActivityThread的main函數,main函數中調用looper.prepar和lopper.loop啓動消息隊列循環機制。最後遠程告知AMS我啓動了。AMS回調handleLauncherAcitivyt加載activity。在handlerLauncherActivity中會經過反射調用Application的onCreate和activity的onCreate以及經過handleResumeActivity中反射調用Activity的onResume
  • 推薦文章:

Fragment

一、談一談Fragment的生命週期?

  • 參考回答:
    • Fragment從建立到銷燬整個生命週期中涉及到的方法依次爲:onAttach()→onCreate()→ onCreateView()→onActivityCreated()→onStart()→onResume()→onPause()→onStop()→onDestroyView()→onDestroy()→onDetach(),其中和Activity有很多名稱相同做用類似的方法,而不一樣的方法有:
      • onAttach():當Fragment和Activity創建關聯時調用;
      • onCreateView():當fragment建立視圖調用,在onCreate以後;
      • onActivityCreated():當與Fragment相關聯的Activity完成onCreate()以後調用;
      • onDestroyView():在Fragment中的佈局被移除時調用;
      • onDetach():當Fragment和Activity解除關聯時調用;
  • 推薦文章:

二、談談Activity和Fragment的區別?

  • 參考回答:
    • 類似點:均可包含佈局、可有本身的生命週期
    • 不一樣點:
      • Fragment相比較於Activity多出4個回調週期,在控制操做上更靈活;
      • Fragment能夠在XML文件中直接進行寫入,也能夠在Activity中動態添加;
      • Fragment可使用show()/hide()或者replace()隨時對Fragment進行切換,而且切換的時候不會出現明顯的效果,用戶體驗會好;Activity雖然也能夠進行切換,可是Activity之間切換會有明顯的翻頁或者其餘的效果,在小部份內容的切換上給用戶的感受不是很好;

三、Fragment中add與replace的區別(Fragment重疊)

  • 參考回答:
    • add不會從新初始化fragment,replace每次都會。因此若是在fragment生命週期內獲取獲取數據,使用replace會重複獲取;
    • 添加相同的fragment時,replace不會有任何變化,add會報IllegalStateException異常;
    • replace先remove掉相同id的全部fragment,而後在add當前的這個fragment,而add是覆蓋前一個fragment。因此若是使用add通常會伴隨hide()和show(),避免佈局重疊;
    • 使用add,若是應用放在後臺,或以其餘方式被系統銷燬,再打開時,hide()中引用的fragment會銷燬,因此依然會出現佈局重疊bug,可使用replace或使用add時,添加一個tag參數;

四、getFragmentManager、getSupportFragmentManager 、getChildFragmentManager之間的區別?

  • 參考回答:
    • getFragmentManager()所獲得的是所在fragment 的父容器的管理器, getChildFragmentManager()所獲得的是在fragment 裏面子容器的管理器, 若是是fragment嵌套fragment,那麼就須要利用getChildFragmentManager();
    • 由於Fragment是3.0 Android系統API版本纔出現的組件,因此3.0以上系統能夠直接調用getFragmentManager()來獲取FragmentManager()對象,而3.0如下則須要調用getSupportFragmentManager() 來間接獲取;

五、FragmentPagerAdapter與FragmentStatePagerAdapter的區別與使用場景

  • 參考回答:
    • 相同點 :兩者都繼承PagerAdapter
    • 不一樣點 :FragmentPagerAdapter的每一個Fragment會持久的保存在FragmentManager中,只要用戶能夠返回到頁面中,它都不會被銷燬。所以適用於那些數據相對靜態的頁,Fragment數量也比較少的那種; FragmentStatePagerAdapter只保留當前頁面,當頁面不可見時,該Fragment就會被消除,釋放其資源。所以適用於那些數據動態性較大、佔用內存較多,多Fragment的狀況;

Service

一、談一談Service的生命週期?

  • 參考回答:Service的生命週期涉及到六大方法
    • onCreate():若是service沒被建立過,調用startService()後會執行onCreate()回調;若是service已處於運行中,調用startService()不會執行onCreate()方法。也就是說,onCreate()只會在第一次建立service時候調用,屢次執行startService()不會重複調用onCreate(),此方法適合完成一些初始化工做;
    • onStartComand():服務啓動時調用,此方法適合完成一些數據加載工做,好比會在此處建立一個線程用於下載數據或播放音樂;
    • onBind():服務被綁定時調用;
    • onUnBind():服務被解綁時調用;
    • onDestroy():服務中止時調用;
  • 推薦文章:

二、Service的兩種啓動方式?區別在哪?

  • 參考回答:Service的兩種啓動模式
    • startService():經過這種方式調用startService,onCreate()只會被調用一次,屢次調用startSercie會屢次執行onStartCommand()和onStart()方法。若是外部沒有調用stopService()或stopSelf()方法,service會一直運行。
    • bindService():若是該服務以前還沒建立,系統回調順序爲onCreate()→onBind()。若是調用bindService()方法前服務已經被綁定,屢次調用bindService()方法不會屢次建立服務及綁定。若是調用者但願與正在綁定的服務解除綁定,能夠調用unbindService()方法,回調順序爲onUnbind()→onDestroy();
  • 推薦文章:

三、如何保證Service不被殺死 ?

  • 參考回答:
    • onStartCommand方式中,返回START_STICKY或則START_REDELIVER_INTENT
      • START_STICKY:若是返回START_STICKY,表示Service運行的進程被Android系統強制殺掉以後,Android系統會將該Service依然設置爲started狀態(即運行狀態),可是再也不保存onStartCommand方法傳入的intent對象
      • START_NOT_STICKY:若是返回START_NOT_STICKY,表示當Service運行的進程被Android系統強制殺掉以後,不會從新建立該Service
      • START_REDELIVER_INTENT:若是返回START_REDELIVER_INTENT,其返回狀況與START_STICKY相似,但不一樣的是系統會保留最後一次傳入onStartCommand方法中的Intent再次保留下來並再次傳入到從新建立後的Service的onStartCommand方法中
    • 提升Service的優先級 在AndroidManifest.xml文件中對於intent-filter能夠經過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,若是數字越小則優先級越低,同時適用於廣播;
    • 在onDestroy方法裏重啓Service 當service走到onDestroy()時,發送一個自定義廣播,當收到廣播時,從新啓動service;
    • 提高Service進程的優先級 進程優先級由高到低:前臺進程 一 可視進程 一 服務進程 一 後臺進程 一 空進程 可使用startForeground將service放到前臺狀態,這樣低內存時,被殺死的機率會低一些;
    • 系統廣播監聽Service狀態
    • 將APK安裝到/system/app,變身爲系統級應用
  • 注意:以上機制都不能百分百保證Service不被殺死,除非作到系統白名單,與系統同生共死

四、可否在Service開啓耗時操做 ? 怎麼作 ?

  • 參考回答:
    • Service默認並不會運行在子線程中,也不運行在一個獨立的進程中,它一樣執行在主線程中(UI線程)。換句話說,不要在Service裏執行耗時操做,除非手動打開一個子線程,不然有可能出現主線程被阻塞(ANR)的狀況;

五、用過哪些系統Service ?

  • 參考回答:

六、瞭解ActivityManagerService嗎?發揮什麼做用

  • 參考回答: ActivityManagerService是Android中最核心的服務 , 主要負責系統中四大組件的啓動、切換、調度及應用進程的管理和調度等工做,其職責與操做系統中的進程管理和調度模塊相似;
  • 推薦文章:

Broadcast Receiver

一、廣播有幾種形式 ? 都有什麼特色 ?

  • 參考回答:
    • 普通廣播:開發者自身定義 intent的廣播(最經常使用),全部的廣播接收器幾乎會在同一時刻接受到此廣播信息,接受的前後順序隨機
    • 有序廣播:發送出去的廣播被廣播接收者按照前後順序接收,同一時刻只會有一個廣播接收器可以收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞,且優先級(priority)高的廣播接收器會先收到廣播消息。有序廣播能夠被接收器截斷使得後面的接收器沒法收到它;
    • 本地廣播:僅在本身的應用內發送接收廣播,也就是隻有本身的應用能收到,數據更加安全,效率更高,但只能採用動態註冊的方式;
    • 粘性廣播:這種廣播會一直滯留,當有匹配該廣播的接收器被註冊後,該接收器就會收到此條廣播;
  • 推薦文章:

二、廣播的兩種註冊方式 ?

  • 參考回答:

三、廣播發送和接收的原理了解嗎 ?(Binder機制、AMS)

ContentProvider

一、ContentProvider瞭解多少?

  • 參考回答:
    • ContentProvider做爲四大組件之一,其主要負責存儲和共享數據。與文件存儲、SharedPreferences存儲、SQLite數據庫存儲這幾種數據存儲方法不一樣的是,後者保存下的數據只能被該應用程序使用,而前者可讓不一樣應用程序之間進行數據共享,它還能夠選擇只對哪一部分數據進行共享,從而保證程序中的隱私數據不會有泄漏風險。
  • 推薦文章:

二、ContentProvider的權限管理?

  • 參考回答:
    • 讀寫分離
    • 權限控制-精確到表級
    • URL控制

三、說說ContentProvider、ContentResolver、ContentObserver 之間的關係?

  • 參考回答:
    • ContentProvider:管理數據,提供數據的增刪改查操做,數據源能夠是數據庫、文件、XML、網絡等,ContentProvider爲這些數據的訪問提供了統一的接口,能夠用來作進程間數據共享。
    • ContentResolver:ContentResolver能夠爲不一樣URI操做不一樣的ContentProvider中的數據,外部進程能夠經過ContentResolver與ContentProvider進行交互。
    • ContentObserver:觀察ContentProvider中的數據變化,並將變化通知給外界。

數據存儲

一、描述一下Android數據持久存儲方式?

  • 參考回答:Android平臺實現數據持久存儲的常見幾種方式:
    • SharedPreferences存儲:一種輕型的數據存儲方式,本質是基於XML文件存儲的key-value鍵值對數據,一般用來存儲一些簡單的配置信息(如應用程序的各類配置信息);
    • SQLite數據庫存儲:一種輕量級嵌入式數據庫引擎,它的運算速度很是快,佔用資源不多,經常使用來存儲大量複雜的關係數據;
    • ContentProvider:四大組件之一,用於數據的存儲和共享,不只可讓不一樣應用程序之間進行數據共享,還能夠選擇只對哪一部分數據進行共享,可保證程序中的隱私數據不會有泄漏風險;
    • File文件存儲:寫入和讀取文件的方法和 Java中實現I/O的程序同樣;
    • 網絡存儲:主要在遠程的服務器中存儲相關數據,用戶操做的相關數據能夠同步到服務器上;

二、SharedPreferences的應用場景?注意事項?

  • 參考回答:
    • SharedPreferences是一種輕型的數據存儲方式,本質是基於XML文件存儲的key-value鍵值對數據,一般用來存儲一些簡單的配置信息,如int,String,boolean、float和long;
    • 注意事項:
      • 勿存儲大型複雜數據,這會引發內存GC、阻塞主線程使頁面卡頓產生ANR
      • 勿在多進程模式下,操做Sp
      • 不要屢次edit和apply,儘可能批量修改一次提交
      • 建議apply,少用commit

三、SharedPrefrences的apply和commit有什麼區別?

  • 參考回答:
    • apply沒有返回值而commit返回boolean代表修改是否提交成功。
    • apply是將修改數據原子提交到內存, 然後異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤,所以,在多個併發的提交commit的時候,他們會等待正在處理的commit保存到磁盤後在操做,從而下降了效率。而apply只是原子的提交到內容,後面有調用apply的函數的將會直接覆蓋前面的內存數據,這樣從必定程度上提升了不少效率。
    • apply方法不會提示任何失敗的提示。 因爲在一個進程中,sharedPreference是單實例,通常不會出現併發衝突,若是對提交的結果不關心的話,建議使用apply,固然須要確保提交成功且有後續操做的話,仍是須要用commit的。

四、瞭解SQLite中的事務操做嗎?是如何作的

  • 參考回答:
    • SQLite在作CRDU操做時都默認開啓了事務,而後把SQL語句翻譯成對應的SQLiteStatement並調用其相應的CRUD方法,此時整個操做仍是在rollback journal這個臨時文件上進行,只有操做順利完成纔會更新db數據庫,不然會被回滾;

五、使用SQLite作批量操做有什麼好的方法嗎?

  • 參考回答:
    • 使用SQLiteDatabase的beginTransaction方法開啓一個事務,將批量操做SQL語句轉化爲SQLiteStatement並進行批量操做,結束後endTransaction()

六、如何刪除SQLite中表的個別字段

  • 參考回答:
    • SQLite數據庫只容許增長字段而不容許修改和刪除表字段,只能建立新表保留原有字段,刪除原表

七、使用SQLite時會有哪些優化操做?

  • 參考回答:
    • 使用事務作批量操做
    • 及時關閉Cursor,避免內存泄露
    • 耗時操做異步化:數據庫的操做屬於本地IO耗時操做,建議放入異步線程中處理
    • ContentValues的容量調整:ContentValues內部採用HashMap來存儲Key-Value數據,ContentValues初始容量爲8,擴容時翻倍。所以建議對ContentValues填入的內容進行估量,設置合理的初始化容量,減小沒必要要的內部擴容操做
    • 使用索引加快檢索速度:對於查詢操做量級較大、業務對查詢要求較高的推薦使用索引

IPC

一、Android中進程和線程的關係? 區別?

  • 參考回答:
    • 線程是CPU調度的最小單元,同時線程是一種有限的系統資源
    • 進程通常指一個執行單元,在PC和移動設備上一個程序或則一個應用
    • 通常來講,一個App程序至少有一個進程,一個進程至少有一個線程(包含與被包含的關係), 通俗來說就是,在App這個工廠裏面有一個進程,線程就是裏面的生產線,但主線程(主生產線)只有一條,而子線程(副生產線)能夠有多個
    • 進程有本身獨立的地址空間,而進程中的線程共享此地址空間,均可以併發執行
  • 推薦文章:

二、如何開啓多進程 ? 應用是否能夠開啓N個進程 ?

三、爲什麼須要IPC?多進程通訊可能會出現的問題?

  • 參考回答:
    • 全部運行在不一樣進程的四大組件(Activity、Service、Receiver、ContentProvider)共享數據都會失敗,這是因爲Android爲每一個應用分配了獨立的虛擬機,不一樣的虛擬機在內存分配上有不一樣的地址空間,這會致使在不一樣的虛擬機中訪問同一個類的對象會產生多份副本。好比經常使用例子(經過開啓多進程獲取更大內存空間、兩個或則多個應用之間共享數據、微信全家桶
    • 通常來講,使用多進程通訊會形成以下幾方面的問題
      • 靜態成員和單例模式徹底失效:獨立的虛擬機形成
      • 線程同步機制徹底實效:獨立的虛擬機形成
      • SharedPreferences的可靠性降低:這是由於Sp不支持兩個進程併發進行讀寫,有必定概率致使數據丟失
      • Application會屢次建立:Android系統在建立新的進程會分配獨立的虛擬機,因此這個過程其實就是啓動一個應用的過程,天然也會建立新的Application
  • 推薦文章:

四、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進行有效性檢測。
  • 推薦文章:

五、Binder機制的做用和原理?

  • 參考回答:
    • Linux系統將一個進程分爲用戶空間內核空間。對於進程之間來講,用戶空間的數據不可共享,內核空間的數據可共享,爲了保證安全性和獨立性,一個進程不能直接操做或者訪問另外一個進程,即Android的進程是相互獨立、隔離的,這就須要跨進程之間的數據通訊方式
      傳統IPC機制原理
  • 一次完整的 Binder IPC 通訊過程一般是這樣:
    • 首先 Binder 驅動在內核空間建立一個數據接收緩存區;
    • 接着在內核空間開闢一塊內核緩存區,創建內核緩存區和內核中數據接收緩存區之間的映射關係,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關係;
    • 發送方進程經過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,因爲內核緩存區和接收進程的用戶空間存在內存映射,所以也就至關於把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通訊。
      Binder機制原理

六、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機制 原理

七、Bundle傳遞對象爲何須要序列化?Serialzable和Parcelable的區別?

  • 參考回答:
    • 由於bundle傳遞數據時只支持基本數據類型,因此在傳遞對象時須要序列化轉換成可存儲或可傳輸的本質狀態(字節流)。序列化後的對象能夠在網絡、IPC(好比啓動另外一個進程的Activity、Service和Reciver)之間進行傳輸,也能夠存儲到本地。
    • 序列化實現的兩種方式:實現Serializable/Parcelable接口。不一樣點如圖:

八、講講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

一、講下View的繪製流程?

  • 參考回答:
    • View的工做流程主要是指measure、layout、draw這三大流程,即測量、佈局和繪製,其中measure肯定View的測量寬/高,layout肯定View的最終寬/高四個頂點的位置,而draw則將View繪製到屏幕
    • View的繪製過程遵循以下幾步:
      • 繪製背景 background.draw(canvas)
      • 繪製本身(onDraw)
      • 繪製 children(dispatchDraw)
      • 繪製裝飾(onDrawScollBars)
  • 推薦文章:

二、MotionEvent是什麼?包含幾種事件?什麼條件下會產生?

  • 參考回答:
    • MotionEvent是手指接觸屏幕後所產生的一系列事件。典型的事件類型有以下:
      • ACTION_DOWN:手指剛接觸屏幕
      • ACTION_MOVE:手指在屏幕上移動
      • ACTION_UP:手指從屏幕上鬆開的一瞬間
      • ACTION_CANCELL:手指保持按下操做,並從當前控件轉移到外層控件時觸發
    • 正常狀況下,一次手指觸摸屏幕的行爲會觸發一系列點擊事件,考慮以下幾種狀況:
      • 點擊屏幕後鬆開,事件序列:DOWN→UP
      • 點擊屏幕滑動一會再鬆開,事件序列爲DOWN→MOVE→.....→MOVE→UP

三、描述一下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方法中調用,用來處理點擊事件,返回結果表示是否消耗當前事件

四、如何解決View的事件衝突 ? 舉個開發中遇到的例子 ?

  • 參考回答:
    • 常見開發中事件衝突的有ScrollView與RecyclerView的滑動衝突、RecyclerView內嵌同時滑動同一方向
    • 滑動衝突的處理規則:
      • 對於因爲外部滑動和內部滑動方向不一致致使的滑動衝突,能夠根據滑動的方向判斷誰來攔截事件。
      • 對於因爲外部滑動方向和內部滑動方向一致致使的滑動衝突,能夠根據業務需求,規定什麼時候讓外部View攔截事件,什麼時候由內部View攔截事件。
      • 對於上面兩種狀況的嵌套,相對複雜,可一樣根據需求在業務上找到突破點。
    • 滑動衝突的實現方法:
      • 外部攔截法:指點擊事件都先通過父容器的攔截處理,若是父容器須要此事件就攔截,不然就不攔截。具體方法:須要重寫父容器的onInterceptTouchEvent方法,在內部作出相應的攔截。
      • 內部攔截法:指父容器不攔截任何事件,而將全部的事件都傳遞給子容器,若是子容器須要此事件就直接消耗,不然就交由父容器進行處理。具體方法:須要配合requestDisallowInterceptTouchEvent方法。

五、scrollTo()和scollBy()的區別?

  • 參考回答:
    • scollBy內部調用了scrollTo,它是基於當前位置的相對滑動;而scrollTo是絕對滑動,所以若是使用相同輸入參數屢次調用scrollTo方法,因爲View的初始位置是不變的,因此只會出現一次View滾動的效果
    • 二者都只能對View內容的滑動,而非使View自己滑動。可使用Scroller有過分滑動的效果
  • 推薦文章:

六、Scroller是怎麼實現View的彈性滑動?

  • 參考回答:
    • 在MotionEvent.ACTION_UP事件觸發時調用startScroll()方法,該方法並無進行實際的滑動操做,而是記錄滑動相關量(滑動距離、滑動時間)
    • 接着調用invalidate/postInvalidate()方法,請求View重繪,致使View.draw方法被執行
    • 當View重繪後會在draw方法中調用computeScroll方法,而computeScroll又會去向Scroller獲取當前的scrollX和scrollY;而後經過scrollTo方法實現滑動;接着又調用postInvalidate方法來進行第二次重繪,和以前流程同樣,如此反覆致使View不斷進行小幅度的滑動,而屢次的小幅度滑動就組成了彈性滑動,直到整個滑動過成結束

七、 invalidate()和postInvalidate()的區別 ?

  • 參考回答:
    • invalidate()與postInvalidate()都用於刷新View,主要區別是invalidate()在主線程中調用,若在子線程中使用須要配合handler;而postInvalidate()可在子線程中直接調用。

八、SurfaceView和View的區別?

  • 參考回答:
    • View須要在UI線程對畫面進行刷新,而SurfaceView可在子線程進行頁面的刷新
    • View適用於主動更新的狀況,而SurfaceView適用於被動更新,如頻繁刷新,這是由於若是使用View頻繁刷新會阻塞主線程,致使界面卡頓
    • SurfaceView在底層已實現雙緩衝機制,而View沒有,所以SurfaceView更適用於須要頻繁刷新、刷新時數據處理量很大的頁面(如視頻播放界面)

九、自定義View如何考慮機型適配 ?

  • 參考回答:
    • 合理使用warp_content,match_parent
    • 儘量的是使用RelativeLayout
    • 針對不一樣的機型,使用不一樣的佈局文件放在對應的目錄下,android會自動匹配。
    • 儘可能使用點9圖片。
    • 使用與密度無關的像素單位dp,sp
    • 引入android的百分比佈局。
    • 切圖的時候切大分辨率的圖,應用到佈局當中。在小分辨率的手機上也會有很好的顯示效果。

你當前所處:Android篇:2019初中級Android開發社招面試解答(上)數據庫

Android篇:2019初中級Android開發社招面試解答(中)canvas

Android篇:2019初中級Android開發社招面試解答(下)緩存

相關文章
相關標籤/搜索