金三銀四,衝擊大廠,你值得擁有的一份2019初中級移動端社招面試總結+解答html
你當前所處:Android篇:2019初中級Android開發社招面試解答(上)android
Android篇:2019初中級Android開發社招面試解答(中)git
Android篇:2019初中級Android開發社招面試解答(下)github
注:由於實際開發與參考答案會有所不一樣,再者怕誤導你們,因此這些面試題答案仍是本身去理解!面試官會針對簡歷中提到的知識點由淺入深提問,因此不要背答案,多理解。面試
- 參考解答:在正常狀況下,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,回調以下
- Activity A 的onPause() → Activity B的onCreate() → onStart() → onResume() → Activity A的onStop();
- 若是B是透明主題又或則是個DialogActivity,則不會回調A的onStop;
- 參考解答:發生條件:異常狀況下(系統配置發生改變時致使Activity被殺死並從新建立、資源內存不足致使低優先級的Activity被殺死)
- 系統會調用onSaveInstanceState來保存當前Activity的狀態,此方法調用在onStop以前,與onPause沒有既定的時序關係;
- 當Activity被重建後,系統會調用onRestoreInstanceState,而且把onSave(簡稱)方法所保存的Bundle對象同時傳參給onRestore(簡稱)和onCreate(),所以能夠經過這兩個方法判斷Activity是否被重建,調用在onStart以後;
![]()
- 推薦文章:
- 參考回答:
- standard標準模式:每次啓動一個Activity都會從新建立一個新的實例,無論這個實例是否已經存在,此模式的Activity默認會進入啓動它的Activity所屬的任務棧中;
- singleTop棧頂複用模式:若是新Activity已經位於任務棧的棧頂,那麼此Activity不會被從新建立,同時會回調onNewIntent方法,若是新Activity實例已經存在但不在棧頂,那麼Activity依然會被從新建立;
- singleTask棧內複用模式:只要Activity在一個任務棧中存在,那麼屢次啓動此Activity都不會從新建立實例,並回調onNewIntent方法,此模式啓動Activity A,系統首先會尋找是否存在A想要的任務棧,若是不存在,就會從新建立一個任務棧,而後把建立好A的實例放到棧中;
- singleInstance單實例模式:這是一種增強的singleTask模式,具備此種模式的Activity只能單獨地位於一個任務棧中,且此任務棧中只有惟一一個實例;
- 推薦文章:
- 參考回答:
- 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在建立時會調用 attach() 方法初始化一個PhoneWindow(繼承於Window),每個Activity都包含了惟一一個PhoneWindow
- Activity經過setContentView其實是調用的 getWindow().setContentView將View設置到PhoneWindow上,而PhoneWindow內部是經過 WindowManager 的addView、removeView、updateViewLayout這三個方法來管理View,WindowManager本質是接口,最終由WindowManagerImpl實現
- 延伸
- WindowManager爲每一個Window建立Surface對象,而後應用就能夠經過這個Surface來繪製任何它想要繪製的東西。而對於WindowManager來講,這只不過是一塊矩形區域而已
- Surface其實就是一個持有像素點矩陣的對象,這個像素點矩陣是組成顯示在屏幕的圖像的一部分。咱們看到顯示的每一個Window(包括對話框、全屏的Activity、狀態欄等)都有他本身繪製的Surface。而最終的顯示可能存在Window之間遮擋的問題,此時就是經過SurfaceFlinger對象渲染最終的顯示,使他們以正確的Z-order顯示出來。通常Surface擁有一個或多個緩存(通常2個),經過雙緩存來刷新,這樣就能夠一邊繪製一邊加新緩存。
- View是Window裏面用於交互的UI元素。Window只attach一個View Tree(組合模式),當Window須要重繪(如,當View調用invalidate)時,最終轉爲Window的Surface,Surface被鎖住(locked)並返回Canvas對象,此時View拿到Canvas對象來繪製本身。當全部View繪製完成後,Surface解鎖(unlock),而且post到繪製緩存用於繪製,經過Surface Flinger來組織各個Window,顯示最終的整個屏幕
- 推薦文章:
- 參考回答:
- 不設置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方法;
- 推薦文章:
- 參考回答:
- 在保證有權限訪問的狀況下,經過隱式Intent進行目標Activity的IntentFilter匹配,原則是:
- 一個intent只有同時匹配某個Activity的intent-filter中的action、category、data纔算徹底匹配,才能啓動該Activity;
- 一個Activity能夠有多個 intent-filter,一個 intent只要成功匹配任意一組 intent-filter,就能夠啓動該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從建立到銷燬整個生命週期中涉及到的方法依次爲: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解除關聯時調用;
- 推薦文章:
- 參考回答:
- 類似點:均可包含佈局、可有本身的生命週期
- 不一樣點:
- Fragment相比較於Activity多出4個回調週期,在控制操做上更靈活;
- Fragment能夠在XML文件中直接進行寫入,也能夠在Activity中動態添加;
- Fragment可使用show()/hide()或者replace()隨時對Fragment進行切換,而且切換的時候不會出現明顯的效果,用戶體驗會好;Activity雖然也能夠進行切換,可是Activity之間切換會有明顯的翻頁或者其餘的效果,在小部份內容的切換上給用戶的感受不是很好;
- 參考回答:
- 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()所獲得的是所在fragment 的父容器的管理器, getChildFragmentManager()所獲得的是在fragment 裏面子容器的管理器, 若是是fragment嵌套fragment,那麼就須要利用getChildFragmentManager();
- 由於Fragment是3.0 Android系統API版本纔出現的組件,因此3.0以上系統能夠直接調用getFragmentManager()來獲取FragmentManager()對象,而3.0如下則須要調用getSupportFragmentManager() 來間接獲取;
- 參考回答:
- 相同點 :兩者都繼承PagerAdapter
- 不一樣點 :FragmentPagerAdapter的每一個Fragment會持久的保存在FragmentManager中,只要用戶能夠返回到頁面中,它都不會被銷燬。所以適用於那些數據相對靜態的頁,Fragment數量也比較少的那種; FragmentStatePagerAdapter只保留當前頁面,當頁面不可見時,該Fragment就會被消除,釋放其資源。所以適用於那些數據動態性較大、佔用內存較多,多Fragment的狀況;
- 參考回答:Service的生命週期涉及到六大方法
- onCreate():若是service沒被建立過,調用startService()後會執行onCreate()回調;若是service已處於運行中,調用startService()不會執行onCreate()方法。也就是說,onCreate()只會在第一次建立service時候調用,屢次執行startService()不會重複調用onCreate(),此方法適合完成一些初始化工做;
- onStartComand():服務啓動時調用,此方法適合完成一些數據加載工做,好比會在此處建立一個線程用於下載數據或播放音樂;
- onBind():服務被綁定時調用;
- onUnBind():服務被解綁時調用;
- onDestroy():服務中止時調用;
- 推薦文章:
- 參考回答:Service的兩種啓動模式
- startService():經過這種方式調用startService,onCreate()只會被調用一次,屢次調用startSercie會屢次執行onStartCommand()和onStart()方法。若是外部沒有調用stopService()或stopSelf()方法,service會一直運行。
- bindService():若是該服務以前還沒建立,系統回調順序爲onCreate()→onBind()。若是調用bindService()方法前服務已經被綁定,屢次調用bindService()方法不會屢次建立服務及綁定。若是調用者但願與正在綁定的服務解除綁定,能夠調用unbindService()方法,回調順序爲onUnbind()→onDestroy();
![]()
- 推薦文章:
- 參考回答:
- 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默認並不會運行在子線程中,也不運行在一個獨立的進程中,它一樣執行在主線程中(UI線程)。換句話說,不要在Service裏執行耗時操做,除非手動打開一個子線程,不然有可能出現主線程被阻塞(ANR)的狀況;
- 參考回答:
![]()
- 參考回答: ActivityManagerService是Android中最核心的服務 , 主要負責系統中四大組件的啓動、切換、調度及應用進程的管理和調度等工做,其職責與操做系統中的進程管理和調度模塊相似;
- 推薦文章:
- 參考回答:
- 普通廣播:開發者自身定義 intent的廣播(最經常使用),全部的廣播接收器幾乎會在同一時刻接受到此廣播信息,接受的前後順序隨機;
- 有序廣播:發送出去的廣播被廣播接收者按照前後順序接收,同一時刻只會有一個廣播接收器可以收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞,且優先級(priority)高的廣播接收器會先收到廣播消息。有序廣播能夠被接收器截斷使得後面的接收器沒法收到它;
- 本地廣播:僅在本身的應用內發送接收廣播,也就是隻有本身的應用能收到,數據更加安全,效率更高,但只能採用動態註冊的方式;
- 粘性廣播:這種廣播會一直滯留,當有匹配該廣播的接收器被註冊後,該接收器就會收到此條廣播;
- 推薦文章:
- 參考回答:
![]()
- 參考回答:
![]()
- 推薦文章:
- 參考回答:
- ContentProvider做爲四大組件之一,其主要負責存儲和共享數據。與文件存儲、SharedPreferences存儲、SQLite數據庫存儲這幾種數據存儲方法不一樣的是,後者保存下的數據只能被該應用程序使用,而前者可讓不一樣應用程序之間進行數據共享,它還能夠選擇只對哪一部分數據進行共享,從而保證程序中的隱私數據不會有泄漏風險。
- 推薦文章:
- 參考回答:
- 讀寫分離
- 權限控制-精確到表級
- URL控制
- 參考回答:
- ContentProvider:管理數據,提供數據的增刪改查操做,數據源能夠是數據庫、文件、XML、網絡等,ContentProvider爲這些數據的訪問提供了統一的接口,能夠用來作進程間數據共享。
- ContentResolver:ContentResolver能夠爲不一樣URI操做不一樣的ContentProvider中的數據,外部進程能夠經過ContentResolver與ContentProvider進行交互。
- ContentObserver:觀察ContentProvider中的數據變化,並將變化通知給外界。
- 參考回答:Android平臺實現數據持久存儲的常見幾種方式:
- SharedPreferences存儲:一種輕型的數據存儲方式,本質是基於XML文件存儲的key-value鍵值對數據,一般用來存儲一些簡單的配置信息(如應用程序的各類配置信息);
- SQLite數據庫存儲:一種輕量級嵌入式數據庫引擎,它的運算速度很是快,佔用資源不多,經常使用來存儲大量複雜的關係數據;
- ContentProvider:四大組件之一,用於數據的存儲和共享,不只可讓不一樣應用程序之間進行數據共享,還能夠選擇只對哪一部分數據進行共享,可保證程序中的隱私數據不會有泄漏風險;
- File文件存儲:寫入和讀取文件的方法和 Java中實現I/O的程序同樣;
- 網絡存儲:主要在遠程的服務器中存儲相關數據,用戶操做的相關數據能夠同步到服務器上;
- 參考回答:
- SharedPreferences是一種輕型的數據存儲方式,本質是基於XML文件存儲的key-value鍵值對數據,一般用來存儲一些簡單的配置信息,如int,String,boolean、float和long;
- 注意事項:
- 勿存儲大型複雜數據,這會引發內存GC、阻塞主線程使頁面卡頓產生ANR
- 勿在多進程模式下,操做Sp
- 不要屢次edit和apply,儘可能批量修改一次提交
- 建議apply,少用commit
- 參考回答:
- apply沒有返回值而commit返回boolean代表修改是否提交成功。
- apply是將修改數據原子提交到內存, 然後異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤,所以,在多個併發的提交commit的時候,他們會等待正在處理的commit保存到磁盤後在操做,從而下降了效率。而apply只是原子的提交到內容,後面有調用apply的函數的將會直接覆蓋前面的內存數據,這樣從必定程度上提升了不少效率。
- apply方法不會提示任何失敗的提示。 因爲在一個進程中,sharedPreference是單實例,通常不會出現併發衝突,若是對提交的結果不關心的話,建議使用apply,固然須要確保提交成功且有後續操做的話,仍是須要用commit的。
- 參考回答:
- SQLite在作CRDU操做時都默認開啓了事務,而後把SQL語句翻譯成對應的SQLiteStatement並調用其相應的CRUD方法,此時整個操做仍是在rollback journal這個臨時文件上進行,只有操做順利完成纔會更新db數據庫,不然會被回滾;
- 參考回答:
- 使用SQLiteDatabase的beginTransaction方法開啓一個事務,將批量操做SQL語句轉化爲SQLiteStatement並進行批量操做,結束後endTransaction()
- 參考回答:
- SQLite數據庫只容許增長字段而不容許修改和刪除表字段,只能建立新表保留原有字段,刪除原表
- 參考回答:
- 使用事務作批量操做
- 及時關閉Cursor,避免內存泄露
- 耗時操做異步化:數據庫的操做屬於本地IO耗時操做,建議放入異步線程中處理
- ContentValues的容量調整:ContentValues內部採用HashMap來存儲Key-Value數據,ContentValues初始容量爲8,擴容時翻倍。所以建議對ContentValues填入的內容進行估量,設置合理的初始化容量,減小沒必要要的內部擴容操做
- 使用索引加快檢索速度:對於查詢操做量級較大、業務對查詢要求較高的推薦使用索引
- 參考回答:
- 線程是CPU調度的最小單元,同時線程是一種有限的系統資源
- 進程通常指一個執行單元,在PC和移動設備上一個程序或則一個應用
- 通常來講,一個App程序至少有一個進程,一個進程至少有一個線程(包含與被包含的關係), 通俗來說就是,在App這個工廠裏面有一個進程,線程就是裏面的生產線,但主線程(主生產線)只有一條,而子線程(副生產線)能夠有多個
- 進程有本身獨立的地址空間,而進程中的線程共享此地址空間,均可以併發執行
- 推薦文章:
- 參考回答:
- 在AndroidMenifest中給四大組件指定屬性android:process開啓多進程模式
- 在內存容許的條件下能夠開啓N個進程
- 推薦講解:
- 參考回答:
- 全部運行在不一樣進程的四大組件(Activity、Service、Receiver、ContentProvider)共享數據都會失敗,這是因爲Android爲每一個應用分配了獨立的虛擬機,不一樣的虛擬機在內存分配上有不一樣的地址空間,這會致使在不一樣的虛擬機中訪問同一個類的對象會產生多份副本。好比經常使用例子(經過開啓多進程獲取更大內存空間、兩個或則多個應用之間共享數據、微信全家桶)
- 通常來講,使用多進程通訊會形成以下幾方面的問題
- 靜態成員和單例模式徹底失效:獨立的虛擬機形成
- 線程同步機制徹底實效:獨立的虛擬機形成
- SharedPreferences的可靠性降低:這是由於Sp不支持兩個進程併發進行讀寫,有必定概率致使數據丟失
- Application會屢次建立:Android系統在建立新的進程會分配獨立的虛擬機,因此這個過程其實就是啓動一個應用的過程,天然也會建立新的Application
- 推薦文章:
- 參考回答:
與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進行有效性檢測。
- 推薦文章:
- 參考回答:
- Linux系統將一個進程分爲用戶空間和內核空間。對於進程之間來講,用戶空間的數據不可共享,內核空間的數據可共享,爲了保證安全性和獨立性,一個進程不能直接操做或者訪問另外一個進程,即Android的進程是相互獨立、隔離的,這就須要跨進程之間的數據通訊方式
![]()
- 一次完整的 Binder IPC 通訊過程一般是這樣:
- 首先 Binder 驅動在內核空間建立一個數據接收緩存區;
- 接着在內核空間開闢一塊內核緩存區,創建內核緩存區和內核中數據接收緩存區之間的映射關係,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關係;
- 發送方進程經過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,因爲內核緩存區和接收進程的用戶空間存在內存映射,所以也就至關於把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通訊。
![]()
- 參考回答:
- 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傳遞數據時只支持基本數據類型,因此在傳遞對象時須要序列化轉換成可存儲或可傳輸的本質狀態(字節流)。序列化後的對象能夠在網絡、IPC(好比啓動另外一個進程的Activity、Service和Reciver)之間進行傳輸,也能夠存儲到本地。
- 序列化實現的兩種方式:實現Serializable/Parcelable接口。不一樣點如圖:
![]()
- 參考回答:
- 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的工做流程主要是指measure、layout、draw這三大流程,即測量、佈局和繪製,其中measure肯定View的測量寬/高,layout肯定View的最終寬/高和四個頂點的位置,而draw則將View繪製到屏幕上
- View的繪製過程遵循以下幾步:
- 繪製背景 background.draw(canvas)
- 繪製本身(onDraw)
- 繪製 children(dispatchDraw)
- 繪製裝飾(onDrawScollBars)
![]()
- 推薦文章:
- 參考回答:
- MotionEvent是手指接觸屏幕後所產生的一系列事件。典型的事件類型有以下:
- ACTION_DOWN:手指剛接觸屏幕
- ACTION_MOVE:手指在屏幕上移動
- ACTION_UP:手指從屏幕上鬆開的一瞬間
- ACTION_CANCELL:手指保持按下操做,並從當前控件轉移到外層控件時觸發
- 正常狀況下,一次手指觸摸屏幕的行爲會觸發一系列點擊事件,考慮以下幾種狀況:
- 點擊屏幕後鬆開,事件序列:DOWN→UP
- 點擊屏幕滑動一會再鬆開,事件序列爲DOWN→MOVE→.....→MOVE→UP
- 參考回答:
- View事件分發本質就是對MotionEvent事件分發的過程。即當一個MotionEvent發生後,系統將這個點擊事件傳遞到一個具體的View上
- 點擊事件的傳遞順序:Activity(Window)→ViewGroup→ View
- 事件分發過程由三個方法共同完成:
- dispatchTouchEvent:用來進行事件的分發。若是事件可以傳遞給當前View,那麼此方法必定會被調用,返回結果受當前View的onTouchEvent和下級View的dispatchTouchEvent方法的影響,表示是否消耗當前事件
- onInterceptTouchEvent:在上述方法內部調用,對事件進行攔截。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的。一旦攔截,則執行ViewGroup的onTouchEvent,在ViewGroup中處理事件,而不接着分發給View。且只調用一次,返回結果表示是否攔截當前事件
- onTouchEvent: 在dispatchTouchEvent方法中調用,用來處理點擊事件,返回結果表示是否消耗當前事件
- 參考回答:
- 常見開發中事件衝突的有ScrollView與RecyclerView的滑動衝突、RecyclerView內嵌同時滑動同一方向
- 滑動衝突的處理規則:
- 對於因爲外部滑動和內部滑動方向不一致致使的滑動衝突,能夠根據滑動的方向判斷誰來攔截事件。
- 對於因爲外部滑動方向和內部滑動方向一致致使的滑動衝突,能夠根據業務需求,規定什麼時候讓外部View攔截事件,什麼時候由內部View攔截事件。
- 對於上面兩種狀況的嵌套,相對複雜,可一樣根據需求在業務上找到突破點。
- 滑動衝突的實現方法:
- 外部攔截法:指點擊事件都先通過父容器的攔截處理,若是父容器須要此事件就攔截,不然就不攔截。具體方法:須要重寫父容器的onInterceptTouchEvent方法,在內部作出相應的攔截。
- 內部攔截法:指父容器不攔截任何事件,而將全部的事件都傳遞給子容器,若是子容器須要此事件就直接消耗,不然就交由父容器進行處理。具體方法:須要配合requestDisallowInterceptTouchEvent方法。
- 參考回答:
- scollBy內部調用了scrollTo,它是基於當前位置的相對滑動;而scrollTo是絕對滑動,所以若是使用相同輸入參數屢次調用scrollTo方法,因爲View的初始位置是不變的,因此只會出現一次View滾動的效果
- 二者都只能對View內容的滑動,而非使View自己滑動。可使用Scroller有過分滑動的效果
- 推薦文章:
- 參考回答:
- 在MotionEvent.ACTION_UP事件觸發時調用startScroll()方法,該方法並無進行實際的滑動操做,而是記錄滑動相關量(滑動距離、滑動時間)
- 接着調用invalidate/postInvalidate()方法,請求View重繪,致使View.draw方法被執行
- 當View重繪後會在draw方法中調用computeScroll方法,而computeScroll又會去向Scroller獲取當前的scrollX和scrollY;而後經過scrollTo方法實現滑動;接着又調用postInvalidate方法來進行第二次重繪,和以前流程同樣,如此反覆致使View不斷進行小幅度的滑動,而屢次的小幅度滑動就組成了彈性滑動,直到整個滑動過成結束
![]()
- 參考回答:
- invalidate()與postInvalidate()都用於刷新View,主要區別是invalidate()在主線程中調用,若在子線程中使用須要配合handler;而postInvalidate()可在子線程中直接調用。
- 參考回答:
- View須要在UI線程對畫面進行刷新,而SurfaceView可在子線程進行頁面的刷新
- View適用於主動更新的狀況,而SurfaceView適用於被動更新,如頻繁刷新,這是由於若是使用View頻繁刷新會阻塞主線程,致使界面卡頓
- SurfaceView在底層已實現雙緩衝機制,而View沒有,所以SurfaceView更適用於須要頻繁刷新、刷新時數據處理量很大的頁面(如視頻播放界面)
- 參考回答:
- 合理使用warp_content,match_parent
- 儘量的是使用RelativeLayout
- 針對不一樣的機型,使用不一樣的佈局文件放在對應的目錄下,android會自動匹配。
- 儘可能使用點9圖片。
- 使用與密度無關的像素單位dp,sp
- 引入android的百分比佈局。
- 切圖的時候切大分辨率的圖,應用到佈局當中。在小分辨率的手機上也會有很好的顯示效果。
你當前所處:Android篇:2019初中級Android開發社招面試解答(上)數據庫