教程android高級面試題_第1頁
教程android高級面試題_第2頁
教程android高級面試題_第3頁
教程android高級面試題_第4頁
教程android高級面試題_第5頁
已閱讀5頁,還剩62頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

五、App五、App移動端獲取網絡數據優(yōu)化的幾1、連接復用:節(jié)省連接建立時間,如開啟kepive。于1、連接復用:節(jié)省連接建立時間,如開啟kepive。于Anrd來說默認情況下nt都開啟了2響連接池的。2、請求合并:即將多個請求合并為一個進行請求,比較常見的就是網頁中的CSSImageSprites。如3、減少請求數據的大小:對于ost請求,body可以做ip壓縮的,header也可以做數據壓縮(不過只支持ttp2.0)。返回數據的oy也可以做zp壓縮,body數據體積可以縮小到原來的30%左右(也可以考慮壓縮返回的json數據的y數據的體積,尤其是針對返回數據格式變化不大的情況,支付寶聊天返回的數據用到了)。4、根據用戶的當前的網絡質量來判斷下載什么質量的圖片(電商用的比較多)5、使用HttpDNS優(yōu)化DNS:DNS存在解析慢和DNS劫持等問題,DNS不僅支持UDP,它還支持TCP,但是大部分標準的DNS都是基于UDPDNS服務器的53端口進行交互。HTTPDNS則不同,顧名思義它是利用HTTP協議與DNS服務器的80端口進行交互。不走傳統的DNS解析,從而繞過運營商的LocalDNS服務器,有效的防止了域名劫持,提高域名解析的效率。參考文客戶端網絡安全實七、安卓的安全這是因為在客戶端中,加載5頁面之前,需要先初始化bViw,在bViw加載WebView的同時,請求H5頁面數據因此常見的方法是全局WebView客戶端代理頁面請求。WebView初始化完成全局WebView客戶端代理頁面請求。WebView初始化完成后向客戶端請求數asset存放離線包除此之外還有一些其他的優(yōu)化手腳本執(zhí)行慢,可以讓腳本最后運行,不阻塞頁面解DNS鏈接慢,可以讓客戶端復用使用的域名與鏈React框架代碼執(zhí)行慢,可以將這部分代碼拆分出來,提前進行解為了加速你的viw,對于頻繁調用的方法,需要盡量減少不必要的代碼。先從onDaw開始,需要特別注意不應該在這里做內存分配的事情,因為它會導致GC,從而導致卡頓。在初始化或者動畫間隙期間做分配內存的動作。不要在動畫正在執(zhí)行的時候做內存分配的事情。你還需要盡可能的減少onDaw被調用的次數,大多數時候導致onDaw都是因為調用了ad().因此請盡量減少調用nvaiat()的次數。如果可能的話,盡量調用含有4個參數的iade()iviate()。沒有參數的invalate會強制重繪整個viw。另外一個非常耗時的操作是請求ayot。任何時候執(zhí)行yut(),會使得nddUI系統去遍歷整個iw的層級來計算出每一個viw的大小。如果找到有沖突的值,它會需要重新計算好幾次。另外需要盡量保持iw的層級是扁平化的,這樣對提高效率很有幫助。如果你有一個復雜的UI,你應該考慮寫一個自定義的iwp來執(zhí)行他的ayot操作。與內置的viw不同,自定義的viw可以使得程序僅僅測量這一部分,這避免了遍歷整個viw4、Close)什么Error、OOM,StackOverFlowError、Runtime,比如說空指針異解決的辦法注意內存的使用和管使用Thread.UncaughtExceptionHandler接5、Java多線程引發(fā)的性能問題,怎么解決二、Framework相Android是一種基于Linux的開放源代碼軟件棧,為廣泛的設備和機型而創(chuàng)建。下圖所示為Android平1.應用程Android隨附一套用于電子郵件、短信、日歷、互聯網瀏覽和聯系人等的核心應用。平臺隨附的應用與Messenger甚至默認鍵盤(有一些例外,例如系統的“設置”應用)。系統應用可用作用戶的應用,以及提供開發(fā)者可從其自己的應用訪問的主要功能。例如,如果您的應用要發(fā)短信,您無需自己構建該功能,可以改為調用已安裝的短信應用向您指定的接收者發(fā)送消息。2、JavaAPI框您可通過以Java語言編寫的您可通過以Java語言編寫的APIAndroidOS的整個功能集。這些API形成創(chuàng)建Android應用所豐富、可擴展的視圖系統,可用以構建應用的UI,包括列表、網格、文本框、按鈕甚至可嵌入的Activity管理器,用于管理應用的生命周期,提供常見的導航返內容提供程序,可讓應用訪問其他應用(例如“聯系人”應用)中的數據或者共享其自己的開發(fā)者可以完全訪問Android系統應用使用的框架API3、系統運原生C/C+許多核心Android系統組件和服務(例如ARTHAL)構建自原生代碼,需要以CC++編寫的原生庫。Android平臺提供Java框架API以向應用顯示其中部分原生庫的功能。例如,您可以通過Android框架的JavaOpenGLAPI訪問OpenGLES,以支持在應用中繪制和操作2D3D圖形。如果開發(fā)的是需要C或C++代碼的應用,可以使用AndroidNDK直接從原生代碼訪問某些原生平臺庫。Android對于運行Android5.0(API級別21)或更高版本的設備,每個應用都在其自己的進程中運行,并且有其自己的AndroidRuntime(ART)實例。ART編寫為通過執(zhí)行DEX文件在低內存設備上運行多個虛擬機,DEX文件是一種專為Android設計的字節(jié)碼格式,經過優(yōu)化,使用的內存很少。編譯工具鏈(例如Jack)將Java源代碼編譯為DEX字節(jié)碼,使其可在Android平臺上運行。ART的部分主要功能包括優(yōu)化的垃圾回收(GC)更好的調試支持,包括專用采樣分析器、詳細的診斷異常和崩潰報告,并且能夠設置監(jiān)視點以監(jiān)控特定字段在Android版本5.0(API級別21)之前,Dalvik是AndroidRuntime。如果您的應用在ART上運行效果很好,那么它應該也可在Dalvik上運行,但反過來不一定。Android還包含一套核心運行時庫,可提供JavaAPI框架使用的Java編程語言大部分功能,包括Java8語言功能4、硬件抽象層硬件抽象層(HAL)提供標準界面,向更高級別的JavaAPI框架顯示設備硬件功能。HAL包含多個庫模塊,其中每個模塊都為特定類型的硬件組件實現一個界面,例如相機或藍牙模塊。當框架API要求訪問設備硬件時,Android系統將為該硬件組件加載庫模塊。5、LinuxAndroid平臺的基礎Linux內核。例如,AndroidRuntimeART)Linux內核來執(zhí)行底層功能,例如線程和低層內存管理。使用Linux內核可讓Android利用主要安全功能,并且允許設備制造商為著對于Android了解Activity的構觸摸事件對應的是MotionEvent類,事件的類型主要有如下三ACTION_MOVE(移動的距離超過一定的閾值會被判定ACTION_MOVE(移動的距離超過一定的閾值會被判定為ACTION_MOVE操作w事件分發(fā)本質就是對MotionEvent事件分發(fā)的過程。即當一個MotionEventiw上。事件分發(fā)過程由三個方法共同完t方法進行ensuper.otrceptTouchEv(),事件攔截分兩種情況:如果該View存在子View且點擊到了該子View則不攔截繼續(xù)分發(fā)給子View處理,此時相當于returnfalse。如果該View沒有子View或者有子View但是沒有點擊中子View(此時相當于普通View),則交由該View的onTouchEvent響應,此時相當于returntrue注意:一般的LinearLayout ScrollView、ListView等ViewGroup則可能攔截,得看具體情onhvnt:方法返回值為true表示當前視圖可以處理對應的事件;返回值為flseonchvent方法進行處理。如果rnsuper.onucvt(v),事件處理分為兩種情況:如果該View是clickable或者longclickable的,則會返回true,表示消費了該事件,與返回true一樣;如果該View不是clickable或者longclickable的,則會返回false,表示不注意:在Android系統中,擁有事件傳遞處理能力的類有以下三三個方法的關系用偽代碼表示如publicbooleandispatchTouchEvent(MotionEvent{booleanconsume=if{consume=}elsecoonsume=}return}通過上面的偽代碼,我們可以大致了解點擊事件的傳遞規(guī)則:對應一個根wopdchhvent就會被調用,如果這個Vwp的Itecthvent方法返回true就表示它要攔截當前事件,接著事件就會交給這個Vwp處理,這時如果它的mOuchListener被設置,則onouch會被調用,否則onuchEvet會被調用。在在onhvt中,如果設置了mOnCckListr,則nck會被調用。只要w的LICKABLE和ONG_ICKABLE有一個為true,onoEve)就會返回true消耗這個事件。如果這個Vw的oIteceptvt方法返回false就表示它不攔截當前事件,這時當前事件就會繼續(xù)傳遞給它的子元素,接著子元素的dpchhvt方法就會被調用,如此反復直到事件被最終處理。2、正常情況下,一個時間序列只能被一個w攔截且消耗。因為一旦一個元素攔截了此事件,那么同一個事件序列內的所有事件都會直接交給它處理(即不會再調用這個w的攔截方法去詢問它是否要攔截了,而是把剩余的OME、TION_DWN等事件直接交給它來處理)。特例:通過將重寫w的onouchEvet返回fe可強行將事件轉交給其他w處理。3、如果w不消耗除TIO_DWN以外的其他事件,那么這個點擊事件會消失,此時父元素的onhvnt并不會被調用,并且當前iw可以持續(xù)收到后續(xù)的事件,最終這些消失的點擊事件會傳遞給Activty處理。4、ViewGroup默認不攔截任何事件(返回false)6、View的enable屬性不影響onTouchEvent的默認返回記住這個圖的傳遞順序,面試的時候能夠畫出來,就很詳細了如果觸摸某個控件,但是又不是在這個控件的區(qū)域上抬起(移動到別的地方了),就會action_cancel點擊事件被攔截,但是想傳到下面的View,如何操作重寫子類的requestDisallowInterceptTouchEvent()方法返回true就不會執(zhí)行父類onInterceptTouchEvent(),即可將點擊事件傳到下面的View如何解決View常見開發(fā)中事件沖突的有SclViw與ecycViw的滑動沖突、RecyclerViw向?;瑒記_突的處理規(guī)則對于由于外部滑動和內部滑動方向不一致導致的滑動沖突,可以根據滑動的方向判斷誰來攔截事件。對于由于外部滑動方對于由于外部滑動和內部滑動方向不一致導致的滑動沖突,可以根據滑動的方向判斷誰來攔截事件。對于由于外部滑動方向和內部滑動方向一致導致的滑動沖突,可以根據業(yè)務需求,規(guī)定何時讓View攔截事件,何時由內部View攔截事對于上面兩種情況的嵌套,相對復雜,可同樣根據需求在業(yè)務上找到突破滑動沖突的實現方法內部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進行處理。具體方法:需要配合qestDisallcethvent方法。加深理DecorView被加載到Window從ActtystartActivy開始,最終調用到ActtyThdhndeanchActty方法來創(chuàng)建Activy,首先,會調用performLaunchActivy方法,內部會執(zhí)行ActivtyoCee方法,從而完成crw和Activy的創(chuàng)建。然后,會調用hdemectt,里面首先會調用rformResumecivity去執(zhí)行Activty的nRsume()方法,執(zhí)行完后會得到一個Activyitcod對象,然后通過r.wind.gtcorViw()的方式得到crw過gtWidM)得到WdwManagr,最終調用其addViw()方法將riw加進去。繪制會從根視圖Rot的prformvrsas()方法開始,從上到下遍歷整個視圖樹,每個iw負責繪制自己,而wop還需要負責通知自己的子w進行繪制操作。理解MeasuSec表示的是一個32位的整形值,它的高2位表示測量模式pMe,低30SecSize。MeasupcVw類的一個靜態(tài)內部類,用來說明應該如何測量這個w。它由三種測量模式,如下:EXTY:精確測量模式,視圖寬高指定為match_pat或具體數值時生效,表示父視圖已經決定了子視圖的精確大小,這種模式下Vw的測量值就是SpecSze的值。T_MOST:最大值測量模式,當視圖的寬高指定為wntentUNSPECIFIED:不指定測量模式父視圖沒有限制子視圖的大小,子視圖可以是想要的任何尺寸,MeasuSec通過將SpMd和SpecSize打包成一個it值來避免過多的對象內存分配,為了方便操作,其提供了打包和解包的方法,打包方法為maMeupc,解包方法為getModegetSiz。普通View的MeasureSpec的創(chuàng)建規(guī)則如對于DecorView而言,它的MeasureSpec由對于DecorView而言,它的MeasureSpec由窗口尺寸和其自身的LayoutParams共同決定;對于普通View,它的MeasureSpec由父視圖的MeasureSpec和其自身的LayoutParams共同決定View繪制流程之首先,在ViewGroup中的measureChildren()方法中會遍歷測量ViewGroup中所有的View,View的可見性處于GONE狀態(tài)時,不對其進行測然后,測量某個指定的Vw時,根據父容器的MeasueSpec和子VwLtas算子w的Mupec。最后,將計算出的MeasueSpec傳入Vw的measue方法,這里iwpiwp是一個抽象類,其測量過程的onMeasue方法需要各個子類去實現。不同的wp子類有不同的布局特性,這導致它們的測量細節(jié)各不相同,如果需要自定義測量過程,則子類可以重寫這個方法。(sMeunsn方法用于設置w的測量寬高,如果w沒有重寫onMeasue方法,則會默認調用etfuze來獲得Vw的寬高)getSuggestMinimumWidth分如果View沒有設置背景,那么返回android:minWidth這個屬性所指定的值,這個值可以為0;如View設置了背景,則返回android:minWidth和背景的最小寬度這兩者中的最大自定義View時手動處理wrap_contentLinearLayout的onMeasure方法實現解析(這里僅分析measureVertical核心源碼系統會遍歷子元素并對每個子元素執(zhí)行measuCdBoLut方法,這個方法內部會調用子元素的measue方法,這樣各個子元素就開始依次進入measue過程,并且系統會通過motaength這個變量來存儲Lierayout在豎直方向的初步高度。每測量一個子元素,motaength就會增加,增加的部分主要包括了子元素的高度以及子元素在豎直方向上的mgin等。在Activity中獲取某個View的寬由于Viw的measue過程和Activy的生命周期方法不是同步執(zhí)行的,如果Vw還沒有測量完畢,那么獲得的寬/高就是0。所以在Ceate、onStart、nsme中均無法正確得到某個w的寬高信息。解決方式如下:wy的窗口得到焦點和失去焦點時均會被調用一次,如果頻繁地進行see也會被頻繁地調用。view.post(runnable):通過post可以將一個runnable投遞到消息隊列的尾部,始化好了然后等待.meue(tihMasu.meue(tihMasupec,ithehtMeasup):match_paent時不知道ntSiz的大小,測不出;具體數值時,直接maeMasupec固定值,然后調用vi..masue就可以了;wntent時,在最大化模式下,用iw構造MeasueSpec是合理的。View的繪制流程之首先,會通過setFe方法來設定w的四個頂點的位置,即w在父容器中的位置。然后,會執(zhí)行到Lut空方法,子類如果是Vwp類型,則重寫這個方法,實現Vwp中所有Vw布局流程。LinearLayout的onLayout方法實現解析(layoutVertical核心源碼其中會遍歷調用每個子VwstlFame方法為子元素確定對應的位置。其中的cp注意:在Vw的默認實現中,w的測量寬/高和最終寬/高是相等的,只不過測量寬/高形成于w的measue過程,而最終寬/高形成于w的yut過程,即兩者的賦值時機不同,測量寬/高的賦值時機稍微早一些。在一些特殊的情況下則兩者不相等:重寫View的layout方法,使最終寬度總是比測量寬/高大100pxw需要多次measue才能確定自己的測量寬/高,在前幾次測量的過程中,其得出的測量寬/可能和最終寬/高不一致,但最終來說,測量寬/高還是和最終寬/高相同。View的繪制流程之Draw的基本流繪制基本上可以分為六個步首先繪制View的背景接著,繪制View的子setWillNotDraw的作如果一個View不需要繪制任何內容,那么設置這個標記位為true以后,系統會進行相應的優(yōu)化默認情況下,View沒有啟用這個優(yōu)化標記位,但是ViewGroup會默認啟用這個優(yōu)化標記位當我們的自定義控件繼承于wp并且本身不具備繪制功能時,就可以開啟這個標記位從而便于系統進行后續(xù)的優(yōu)化。當明確知道一個ViewGroup需要通過onDraw來繪制內容時,我們需要顯示地WILL_NOT_DRAW這個標記位Requestlayout,onlayout,onDraw,DrawChild區(qū)別與聯requestLayout()方法會導致調用measure()過程layout()過程,將會根據標志位判斷是否需要onLayout()方法:如果該View是ViewGroup對象,需要實現該方法,對每個子視圖進行布局onDraw()方法:繪制視圖本身(每個View都需要重載該方法,ViewGroup不需要實現該方法)drawChild():去重新回調每個子視圖的draw()方法invalidate()postInvalidate()的區(qū)別vle()與ostIvle()與ostInvadt()都用于刷新w,主要區(qū)別是nvalt()hnlr;而ostIalde()可在子線程中直接調用。更詳細的內容請點擊這Android中進程和線程的關系?區(qū)別線程是CPU調度的最小單元,同時線程是一種有限的系統資源;而進程一般指一個執(zhí)行單元PC和移動設備上指一個程序或者一個應一般來說,一個App程序至少有一個進程,一個進程至少有一個線程(包含與被包含的關系),通俗來講就是,在App這個工廠里面有一個進程,線程就是里面的生產線,但主線程(即主生產線)只有一條,而子線程(即副生產線)可以有多個。進程有自己獨立的地址空間,而進程中的線程共享此地址空間,都可以并發(fā)執(zhí)如何開啟多進程?應用是否可以開啟N個進程ts個進程。所有運行在不同進程的四大組件(Activy、ServeRciverntentver)共享數據都會失敗,這是由于dod為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。比如常用例子()。一般來說,使用多進程通信會造成如下幾方面的問題Shedencs的可靠性下降:這是因為Sp不支持兩個進程并發(fā)進行讀寫,有一定幾率導致數據丟失。Applation會多次創(chuàng)建:Andd系統在創(chuàng)建新的進程時會分配獨立的虛擬機,所以這個過程其實就是啟動一個應用的過程,自然也會創(chuàng)建新的Appication。Android中IPC方式、各種方式優(yōu)缺點AIL(AndidInterfacee?nitinLuAIL(AndidInterfacee?nitinLue,dod接口定義語言):如果在一個進程中要調用另一個進程中對象的方法,可使用AIL生成可序列化的參數,AIL會生成一個服務端對象的代理類,通過它客戶端可以實現間接調用服務端對象的方法。Stub類:Binder的實現類,服務端通過這個類來提供服Proxy類:服務端的本地代理,客戶端通過這個類調用服務端客戶端調用,將服務端返回的Bder對象,轉換成客戶端所需要的AIL接口類型的對象。如果客戶端和服務端位于同一進程,則直接返回tubStpxy對象。asBinder():根據當前調用情況返回代理Proxy的Binder對象運行在服務端的Binder線程池中,當客戶端發(fā)起跨進程請求時,遠程請求會通過系統底層由此方法來處理transact():運行在端,當客戶端發(fā)起遠程請求的同時將當前線程掛起。之后調用服務端的onTransact()直到遠程請求當有多個業(yè)務模塊都需要AIL來進行IPC,此時需要為每個模塊創(chuàng)建特定的al文件,那么相應的Serve就會很多。必然會出現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立Binder連接池,即將每個業(yè)務模塊的Bnder請求統一轉發(fā)到一個遠程Serve中去執(zhí)行,從而避免重復創(chuàng)建Serve。工作原理:每個業(yè)務模塊創(chuàng)建自己的AIL接口并實現此接口,然后向服務端提供自己的唯一標識和其對應的Binder對象。服務端只需要一個Service并提供一個urydr接口,它會根據業(yè)務模塊的特征來返回相應的Binder對象,不同的業(yè)務模塊拿到所需的Binder對象后就可以進行遠程方法的調用了。為什么選擇為什么選用Binder,在討論這個問題之前,我們知道Andd也是基于nx內核,nx管道:在創(chuàng)建時分配一個page大小的內存,緩存區(qū)大小比較有消息隊列:信息復制兩次,額外的CPU消耗;不合適頻繁或信息量大的通共享內存:無須復制,共享緩沖區(qū)直接附加到進程虛擬地址空間,速度快;但進程間的同步問題操作系統無法實現,必須各進程利用同步工具解決;套接字:作為更通用的接口,傳輸效率低,主要用于不同機器或跨網絡的通信號量:常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。不適用于信息交換,更適用于進程中斷控制,比如非法內存訪問,殺死某個進程等;既然有現有的IPC方式,為什么重新設計一套Binder機制呢。主要是出于以上三個方面的考1、效率:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從d進程架構角度分析:對于消息隊列、Soct和管道來說,數據先從發(fā)送方的緩存區(qū)拷貝到內核開辟的緩存區(qū)中,再從內核緩存區(qū)拷貝到接收方的緩存區(qū),一共兩次拷貝,如圖:而對于Bder而對于Bder來說,數據從發(fā)送方的緩存區(qū)拷貝到內核的緩存區(qū),而接收方的緩存區(qū)與內核的緩存區(qū)是映射到同一塊物理地址的,節(jié)省了一次數據拷貝的過程,如圖:共享內存不需要拷貝,Binder的性能僅次于共享內存2、穩(wěn)定性:上面說到共享內存的性能優(yōu)于Bder,那為什么不采用共享內存呢,因為共享內存需要處理并發(fā)同步問題,容易出現死鎖和資源競爭,穩(wěn)定性較差。Sct雖然是基于S架構的,但是它主要是用于網絡間的通信且傳輸效率較低。Bder基于C/S架構,Servr端與lt端相對獨立,穩(wěn)定性較好。3、安全性:傳統LinuxIPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;Binder機制的作用和原理Linux系統將一個進程分為用戶空間和內核空間。對于進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,為了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即dod的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式。普通的跨進程通信方式一般需要2次內存拷貝,如下圖所示:一次完整的Binder一次完整的BinderIPC通信過程通常是這樣首先Binder驅動在內核空間創(chuàng)建一個數據接收緩存接著在內核空間開辟一塊內核緩存區(qū),建立內核緩存區(qū)和內核中數據接收緩存區(qū)之間的映射關系,以及內核中數據接收緩存區(qū)和接收進程用戶空間地址的映射關系。發(fā)送方進程通過系統調用coymr()將數據coy到內核中的內核緩存區(qū),由于內核緩存區(qū)和接收進程的用戶空間存在內存映射,因此也就相當于把數據發(fā)送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。Binder框架中ServiceManager的作用Binder框架是基于C/S架構的Binder框架是基于C/S架構的。由一系列的組件組成,包括Client、Server、ServiceManager、Server&Client:服務器&客戶端。在Binder驅動和ServiceManager提供的基礎設施上,進行Bnder驅動(如同路由器):負責進程之間bnr通信的建立,計數管理以及數據的傳遞交互等底層支持。最后,結合Android跨進程通信:圖文詳解Binder機制的總結圖來綜合理解一Binder的完整定從進程Binder的完整定從進程間通信的角度看,Binder是一種進程間通信的機制從Server進程的角度看,Binder指的是Server中的Binder實體對象從Clt進程的角度看,Binder指的是Bnder代理對象,是Bnder實體對象的一個遠程代理;從傳輸過程的角度看,Bder是一個可以跨進程傳輸的對象;Bder手寫實現簡化版AMS(AIDL實現與Binder相關的幾個類的職責IBinder:跨進程通信的Base接口,它聲明了跨進程通信需要實現的一系列抽象方法,實現了這個接口就說明可以進行跨進程通信,Clt和Server都要實現此接口。Itace:這也是一個Base接口,用來表示Servr提供了哪些能力,是Cet和vr議。Bnder:提供Bnder服務的本地對象的基類,它實現了IBnder類。a類,這個類表示代理對象它同樣實現了IBinder接口,不過它的很多實現都交由e層處理。t中拿到的實際上是這個代理對象tub:這個類在編譯al個代理對象tub:這個類在編譯al文件后自動生成,它繼承自Binder,表示它是一個BderIInterface接口,表明它的子類需要實現Servr將要提供的具體能力(即al文件中聲明的方法)。xy:它實現了IInterface接口,說明它是Bder通信過程的一部分;它實現了l中聲明的方法,但最終還是交由其中的meme成員來處理,說明它是一個代理對象,meme上就是Binrxy。l文件只是用來定義/S交互的接口,dod在編譯時會自動生成相應的Java類,生成的類中包含了tub和Pxy靜態(tài)內部類,用來封裝數據轉換的過程,實際使用時只關心具體的Java接口類即可。為什么tub和xy是靜態(tài)內部類呢?這其實只是為了將三個類放在一個文件中,提高代碼的聚合性。通過上面的分析,我們其實完全可以不通過aidl,手動編碼來實現Bnder的通信,下面我們通過編碼來實現ActivyMaarService:1、首先定義IActivityManager接口2、然后,實現ActivityManagerService側的本地Binder對象基類//名稱隨意,不一定叫IActivityManager{publicstaticIActivityManagerasInterface(IBinder{if(obj==null){returnnull;}IActivityManagerin=(IActivityManager)if(in!={return}returnnew}publicIBinder{return}protectedbooleanonTransact(intcode,Parceldata,ParcelthrowsRemoteException{switch(code)//獲取binderintpublicinterfaceIActivityManagerextendsIInterfaceStringDESCRIPTOR=intTRANSACTION_startActivity=IBinder.FIRST_CALL_TRANSACTION+}casereturntrue;//casereturntrue;//啟動activity,從data中反序列化出intent參數后,直接調用子類caseIActivityManager.TRANSACTION_startActivity:intresult=this.startActivity(intent);returntrue;}returnsuper.onTransact(code,data,reply,}}3、接著,實現Client側的代理對象4、最后,實現Binder本地對象(IActivityManager接口privateIBindermRemote;publicActivityManagerProxy(IBinder{mRemote=}publicIBinderasBinder(){returnmRemote;}publicintstartActivity(Intentintent)throwsRemoteException{Parceldata=Parcel.obtain();Parcelreply=Parcel.obtain();intresult;try//將intent參數序列化,寫入dataintent.writeToParcel(data,//調用BinderProxy對象的transact方法,交由Binder reply,//等待serverresult=}finally}return}}簡化版的ActivityManagerService到這里就已經簡化版的ActivityManagerService到這里就已經實現了,剩下就是Client只需要獲取到AMS的代理IActivityManager就可以通信了寫給Android應用工程師的Binder原理剖析老羅Binder機制分析系列或Android系統源代碼情景分析Binder章5、Android系統啟動流程是什么?(提示:init進程->ZygoteSystemServer應用進程Android系統啟動的核心流程如1啟動電源以及系統啟動:當電源按下時引導芯片從預定義的地方(固化在ROM)載引導程序Boer到M,然后執(zhí)行。2引導程序BootLoader:otLoader是在Andid系統開始運行前的一個小程序,主要用于把系統OS拉起來并運行。3Linux內核啟動:當內核啟動時,設置緩存、被保護存儲器、計劃列表、加載驅動。當其完成系統設置時,會先在系統文件中尋找it.c文件,并啟動t進程。4、init進程啟動:初始化和啟動屬性服務,并且啟動Zygote進程5Zygote進程啟動:創(chuàng)建JVM并為其注冊JI方法,創(chuàng)建服務器端Soct,啟動Systemvr進程。6SystemServer進程啟動:啟動Binder線程池和SystemveManagr服務。7Launer啟動:被Systvr進程啟動的AMS會啟動anceranchr是因為啟動程序(主界面也是一個app),發(fā)現了在這個程序中存在一個設置為的所以這個launcher會把icon提出來,放在主界面上。當用戶點擊icon的時候,發(fā)出一個publicclassActivityManagerServiceextends{publicintstartActivity(Intentintent)throwsRemoteExceptionreturn0;}}跳過去可以跳到任意允許的頁面,如一個程序可以下載,那么真正下載的頁面可能不是首頁()跳過去可以跳到任意允許的頁面,如一個程序可以下載,那么真正下載的頁面可能不是首頁(),這時還是構造一個Itt,startActivy。這個ntent中的action可能有多種viw,ad都有可能。系統會根據第三方程序向系統注冊的功能,為你的Itet選擇可以打開的程序或者頁面。所以唯一的一點不同的是從cn的點擊啟動的ntentactn是相對單一的,從程序中跳轉或者啟動可能樣式更多一些。本質是相同的。7、AMSActivityManagerServices,簡稱AMS,服務端對象,負責系統中所有Activity的生命周期ActivyThad,App的真正入口。當開啟App之后,調用m)是傳說的UI線程或者叫主線程。與ActivityManerServce一起完成Activy的管理工作。之間的交互。在en的生命周期時,通過d的代理對象與Instrumtn,每一個應用程序只有一個Imetain對象,每個Ativity內都有一個對該對象的引用,Instrntation可以理解為應用進程的管家,ActtyThd要創(chuàng)建或暫停某個Activty時,都需要通過Insrntation來進行具體的操作。點擊應用圖標后會去啟動應用的ancherActivity,如果urActivtyActivty的啟動流程。Activity的啟動流程圖(放大可查看)如下所Intentintent=整個流程涉及的主要角色Instrumentation:監(jiān)控應用與整個流程涉及的主要角色Instrumentation:監(jiān)控應用與系統相關的交互行為AMS:組件管理調度中心,什么都不干,但是什么都ActivityStarter:Activity啟動的控制器,處理Intent與Flag對Activity啟動的影響,具體說來有尋找符合啟動條件的Activity,如果有多個,讓用戶選擇;2校驗啟動參數的合法性;3返回int數,代表Activity是否啟動成功這個類的作用你從它的名字就可以看出來,它用來管理任務棧。ActivityStack:用來管理任務棧ActivyThad:最終干活的人,Activy、Serve、astRcr注:這里單獨提一下Activytackpisior,這是高版本才有的類,它用來管理多個,早期的版本只有一個Activtytack對應著手機屏幕,后來高版本支持多屏以后,就有了多個ctivtytk,于是就引入了ctytackpsr用來管理多個ctivtytk。整個流程主要涉及四個進調用者進程,如果是在桌面啟動應用就是Launcher應用進程ActivityManagerService等待所在的SystemServer進程,該進程主要運行著系統服務組件。新啟動的應用進程,該進程就是用來承載應用運行的進程了,它也是應用的主線程(就是主線程),處理組件生命周期、界面繪制等相關事情。有了以上的理解,整個流程可以概括如ry)的請求以的方式發(fā)。接收到啟動請求后,交付rg等信息,然后再交給Ak進棧相關流程。同時以tek3、Zygote接收到新進程創(chuàng)建請求后fork出新進程最后,再看看另一幅啟動流程圖來加深理繼承BroadcastReceiver,重寫onReceive()方法r注冊廣播。r發(fā)送廣播。WindwManWindwManer的實現是WindanagerImpl,其再委托WindMngrGlbl來對Wndw進行操作,其中有四種st分別儲存對應的w、VootImpl、WindManer.LayoutPas和正在被刪除的w。Windw的實體是存在于遠端的WdwManrSice,所以增刪改Wdw個st然后通過wootImpl重繪Vw,通過Wdssin(每Windw個對應一個)在遠端修改Windw。APK的安裝流程如下所復制APK到/data/app目錄下,解壓并掃描安裝包資源管理器解析APK里的資源文件/目錄下創(chuàng)建對應的應用數據目錄。x文件進行優(yōu)化,并保存在e將dMat文件解析出的四大組件信息注冊到PackaeMangrSrvice安裝完成后,發(fā)送廣播。15、Android的打包流程?(即描述清點擊Android的build按鈕后發(fā)生了什么?)apkddod的包文件APK分為兩個部分:代碼和資源,所以打包方面也分為資源打包和代碼打包兩個方面,下面就來分析資源和代碼的編譯打包原理。APK整體的的打包流程如下圖所具體說來通過AAPT工具進行資源文件(包括AndMnfest.xml、布局文件、各種xml資源等)生成java文件。通過AIDL工具處理AIDL文件,生成相應的Java文件通過JavaCompiler通過AIDL工具處理AIDL文件,生成相應的Java文件通過JavaCompiler編譯R.java、Java接口文件、Java源文件,生成.class文件通過dx命令,將.class文件和第三方庫中的.class文件處理生成classs.d,該過程主要完成字節(jié)碼轉換成k字節(jié)碼,壓縮常量池以及清除冗余信息等工作。通過Apkdr工具將資源文件、DEX文件打包生成APK文件。通過Jarsger工具,利用KyStoe對生成的APK如果是正式版的APK,還會利用ZpAlign工具進行對齊處理,對齊的過程就是將APK文件中所有的資源文件距離文件的起始距位置都偏移4字節(jié)的整數倍,這樣通過內存映射訪問APK文件的速度會更快,并且會減少其在設備上運行時的內存占用。apk組為什么要簽確保Apk來源的真實性確保Apk沒有被第三方篡什么是簽名在Ak中寫入一個“指紋”。指紋寫入以后,Ak中有任何修改,都會導致這個指紋無效,Andod安裝Ak進行簽名校驗時就會不通過,從而保證了安全性。數字摘對一個任意長度的數據,通過一個ash算法計算后,都可以得到一個固定長度的二進制數據,這個數據就稱為“摘要”。補充散列算法的基礎原理:將數據(如一段文字)運算變?yōu)榱硪还潭ㄩL度SHA-1:在密碼學中,SHA-1(安全散列算法1)是一種加密散列函數,它接受輸入并產生一個位(20字節(jié))散列值,稱為消息摘要M5M5消息摘要算法(英語:M5Message-Dtlgrtm),一種被廣泛使用的密碼散列函數,可以產生出一個28位16字節(jié))的散列值(ashvalue),致SHA-2:名稱來自于安全散列算法2(英語:SecureHashAlgorithm2)的縮寫,一種密碼散列函SHA-512、SHA-512/224、SHA-512/256特征唯一固定長度:比較常用的Hsh算法有M5和SSHA-512、SHA-512/224、SHA-512/256特征唯一固定長度:比較常用的Hsh算法有M5和S1,MD5的長度是28拉,SA1的長度是10不可逆性簽名和校驗的主要過簽名就是在摘要的基礎上再進行一次加密,對摘要加密后的數據就可以當作數字簽簽名過程1、計算摘要:通過Hash算法提取出原始數據的摘2、計算簽名:再通過基于密鑰(私鑰)的非對稱加密算法對提取出的摘要進行加密,加密后的數據就是簽名信息。3、寫入簽名:將簽名信息寫入原始數據的簽名區(qū)塊校驗過程1、首先用同樣的Hash算法從接收到的數據中提取出摘2、解密簽名:使用發(fā)送方的公鑰對數字簽名進行解密,解密出原始摘3、比較摘要:如果解密后的數據和提取的摘要一致,則校驗通過;如果數據被第三方篡改過,解密后的數據和摘要將會不一致,則校驗不通過。數字證如何保證公鑰的可靠性呢?答案是數字證書,數字證書是身份認證機構(rti?cateAuthority)的,包含了以下信息:證書頒發(fā)機證書頒發(fā)機構簽接收方收到消息后,先向CA驗證證書的合法性,再進行簽名校注意:Ak的證書通常是自簽名的,也就是由開發(fā)者自己制作,沒有向CA機構申請。dod在安裝Apk時并沒有校驗證書本身的合法性,只是從證書中提取公鑰和加密算法,這也正是對第三方Apk簽名后,還能夠繼續(xù)在沒有安裝這個Apk的系統中繼續(xù)安裝的原因。keystore和證書格ytoe文件中包含了私鑰、公鑰和數字證書。根據編碼不同,ystoe文件分為很多種,did使用的是Java標準yste格式JKS(JavayStoage),所以通過AndidStudio導出的ystoe文件是.s結尾的。EnhancedMail)和der(DistinguishedEncodingRules)。jks使用的是der格式,Android也支持直兩種證書編碼格式的區(qū)DER(DistinguishedEncoding二進制格式,所有類型的證書和私鑰都可以存儲為der格式PEM(PrivacyEnhancedbase64編碼,內容以BEGINxxxbase64編碼,內容以BEGINxxx開頭,以END 結尾jarsigner和apksigner的區(qū)dod提供了兩種對Ak的簽名方式,一種是基于JAR的簽名方式,另一種是基于Apk的簽名方式,它們的主要區(qū)別在于使用的簽名文件不一樣:rsigner使用ystoe文件進行簽名;pksger除了支持使用ystoe文件進行簽名外,還支持直接指定pem證書文件和私鑰進行簽名。在簽名時,除了要指定keystore文件和密碼外,也要指定alias和key的密碼,這是為什么呢ytoe是一個密鑰庫,也就是說它可以存儲多對密鑰和證書,ystoe的密碼是用于保護ystoe本身的,一對密鑰和證書是通過is來區(qū)分的。所以jarsigner是支持使用多個證書對Apk進行簽名的,pksger也同樣支持。AndroidApkV1簽名原1、解析出CERT.RSA文件中的證書、公鑰,解密CERT.RSA中的加密數據2、解密結果和CERT.SF的指紋進行對比,保證CERT.SF沒有3、而CERT.SF中的內容再和MANIFEST.MF指紋對比,保證MANIFEST.MF文件沒有被篡改4、MANIFEST.MF中的內容和APK所有文件指紋逐一對比,保證APK沒有被篡改JVM和DalvikJVM:.java->javac->.class->jar->架構:堆和棧的架構DVM:.java->javac->.class->dx.bat->架構:寄存器(cpu上的一塊高速緩存Android2個虛擬機的區(qū)別(一個5.0之前,一個5.0之后什么是akDk是Goe公司自己設計用于Andid平臺的Java虛擬機。Dlvik虛擬機是Gle等廠商合作開發(fā)的Andid移動設備平臺的核心組成部分之一,它可以支持已轉換為.x(即atl)格式的Java應用程序的運行,.x格式是專為vkak經過優(yōu)化,允許在有限的內存中同時運行多個虛擬機的實例,并且每一Dk應用作為獨立的ix進程執(zhí)行。獨立的進程可以防止在虛擬機崩潰的時候所有程序都被關閉什么是AT:Andd操作系統已經成熟,Goole的dd團隊開始將注意力轉向一些底層組件,其中之一是負責應用程序運行的k運行時。Gooe開發(fā)者已經花了兩年時間開發(fā)更快執(zhí)行效率更高更省電的替代ART運行時。ART代表Andidum,其處理應用程序執(zhí)行的方式完全不同于ak,k是依靠一個Jus-nTime(JIT)編譯器去解釋字節(jié)碼。開發(fā)者編譯后的應用代碼需要通過一個解釋器在用戶的設備上運行,這一機制并不高效,但讓應用能更容易在不同硬件和架構上運行。ART則完全改變了這套做法,在應用安裝的時候就預編譯字節(jié)碼為機器語言,這一機制叫Ahd-OfTm(T)編譯。在移除解釋代碼這一過程后,應用程序執(zhí)行將更有效率,啟動更ART優(yōu)點系統性能的顯著提升支持更低的硬件ART缺點ART缺點Java調用在Java中聲明Native方法(即需要調用的本地方法編譯上述Java源文件javac(得到.class文件)3過javah命令導出JNI的頭文件(.h文件)使用Java需要交互的本地代碼實現在Java中聲明的Native方法編譯.so庫文通過Java命令執(zhí)C++調用Java程序,最終實現Java調用從classpath路徑下搜索ClassMethod這個類,并返回該類的Class對象創(chuàng)建該類的實例調用對象的實例方法JNIEXPORTvoid(JNIEnv*env,jclasscls){jclassclazz=NULL;jobjectjobj=jmethodIDmid_instance=NULL;jstringstr_arg=NULL;//1、從classpath路徑下搜索ClassMethod這個類,并返回該類的Classif(clazz==NULL){}//2、獲取類的默認構造方法if(mid_construct==NULL){}//3、查找實例方法的三、Android優(yōu)秀三三、Android優(yōu)秀三方這個庫是做什么用的網絡底層庫,它是基于ttp協議封裝的一套請求客戶端,雖然它也可以開線程,但根本上它更偏向真正的請求,跟Httpnt,Htpnectn的職責是一樣的。其中封裝了網絡請求get、pt等底層操作的實現。為什么要在項目中使用這個OkHttp提供了對最新的HTTP協議版本HTTP/2SPDY的支持,這使得對同一個主機發(fā)出的所如果HTTP/2和SPDY不可用,OkHttp會使用連接池來復用連接以提高效OkHttp提供了對GZIP的默認支持來降低傳輸內容的大OkHttp也提供了對HTTP響應的緩存機制,可以避免不必要的網絡請求。當網絡出現問題時,OkHttp會自動重試一個主機的多個IP地址。這個庫都有哪些用法?對應什么樣的使用場get、post請求、上傳文件、上傳表單等這個庫的優(yōu)缺點是什么,跟同類型庫的比優(yōu)點:在上if(mid_instance==NULL)}//4if(jobj==NULL){法}//5str_arg=(*env)->NewStringUTF(env,"我是實例方法//刪除局部}缺點:使用的時候仍然需要缺點:使用的時候仍然需要自己再做一層封這個庫的核心實現原理是什么?如果讓你實現這個庫的某些核心功能,你會考慮怎么去實OkHtp內部的請求流程:使用Okp會在請求的時候初始化一個l的實例,然后執(zhí)行它的ecute()方法或eue)方法,內部最后都會執(zhí)行到etRpnseWntecept()方法,這個方法里面通過攔截器組成的責任鏈,依次經過用戶自定義普通攔截器、重試攔截器、橋接攔截器、緩存攔截器、連接攔截器和用戶自定義網絡攔截器以及訪問服務器攔截器等攔截處理過程,來獲取到一個響應并交給用戶。其中,除了OKHtp的內部請求流程這點之外,緩存和連接這兩部分內容也是兩個很重要的點,掌握了這3點就說明你理解了OkHttp。各個攔截器的作用rgntectr:請求時,對必要的Header進行一些添加,接收響應時,移除必要的rIecer:負責讀取緩存直接返回(根據請求的信息和緩存的響應的信息來判斷是否存在緩存可用)、更新緩存1、判斷連接是否可用,不可用則從CnectnPool獲取連接,ontnPoolonectnPool。3、使用連接復用省去了進行TCP和TLS握手的一個過程。networkInterceptors:用戶定義網絡攔截CallServerInterceptor:負責向服務器發(fā)送請求數據、從服務器讀取響你從這個庫中學到什么有價值的或者說可借鑒的設計思使用責任鏈模式實現攔截器的分層設計,每一個攔截器對應一個功能,充分實現了功能解耦,易維手寫攔截器網絡請求緩存處理,okhttp如何處理網絡緩存的HttpUrlConnectionokhttp關系?oly:支持TTPS。緩存、異步請求,不支持同步請求。協議類型是1.0,Htt/.用的是tpUrlnectn/ttpCnt,數據讀寫使用的IO。OkHttp:支持HTTPS。緩存、異步請求、同步請求。協議類型是Http/1.0Http/1.1SPDY,Http/2.0,Okhttp的子系統層級結構圖如下所示網絡配置層:利用Bu網絡配置層:利用Buer模式配置各種參數,例如:超時時間、攔截器等,這些參數都會由Okttp分發(fā)給各個需要的子系統。重定向層:負責重定向Header拼接層:負責把用戶構造的請求轉換為發(fā)送給服務器的請求,把服務器返回的響應轉換為對用戶友好的響應。HTTP緩存層:負責讀取緩存以及更新緩連接層:連接層是一個比較復雜的層級,它實現了網絡協議、內部的攔截器、安全性認證,連接與連接池等功能,但這一層還沒有發(fā)起真正的連接,它只是做了連接器一些參數的處理。數據響應層:負責從服務器讀取響應的數在整個Okhttp的系統中,我們還要理解以下幾個關鍵角OkHttpClient:通信的客戶端,用來統一管理發(fā)起請求與解析響RequestBody:請求體,用來提交流、表單等請求信息Response:HTTP請求的響應,獲取響應信息,例如:響應headerIr是請求攔截器,負責攔截并處理請求,它將網絡請求、緩存、透明壓縮等功能都統一起來,每個功能都是一個Itcer,所有的Ictr最終連接成一個RouteDatabase:記錄連接失敗的Route黑名單自己去設計網絡請求框架,怎么從網絡加載一個10M的圖片,說下注意事項?http怎么知道文件過大是否傳輸完畢的響應?談談你對ebSocet的理解?WebSocket與socket的區(qū)這個庫是做什么用的Retro?t是一個RESTful的HTTP網絡請求框架的封裝。Retro?t2.0開始內置OkHttp,前者專注于接為什么要在項目中使用這個1、功能強支持同步、支持多種數據的解析&序列化格式2、簡潔易采用大量設計模式簡化使3、可擴展性好功能模塊高度封解耦徹底,如自定義這個庫都有哪些用法?對應什么樣的使用場任何網絡場景都應該優(yōu)先選擇,特別是后臺API遵循RestfulAPI設計風格&項目中使用到RxJava這個庫的優(yōu)缺點是什么,跟同類型庫的比優(yōu)點:在上缺點:擴展性差,高度封裝所帶來的必然后果,如果服務器不能給出統一的API理。這個庫的核心實現原理是什么?如果讓你實現這個庫的某些核心功能,你會考慮怎么去實et?t主要是在eate方法中采用動態(tài)代理模式(通過訪問代理對象的方式來間接訪問目標對象)實現接口方法,這個過程構建了一個SrveMhd對象,根據方法注解獲取請求方式,參數類型和參數注解拼接請求的鏈接,當一切都準備好之后會把數據添加到Rtt的euestBude中。然后當我們主動發(fā)起網絡請求的時候會調用khttp發(fā)起網絡請求,kttp的配置包括請求方式,UL等在Ret的euestBudrl)方法中實現,并發(fā)起真正的網絡請求。你從這個庫中學到什么有價值的或者說可借鑒的設你從這個庫中學到什么有價值的或者說可借鑒的設計思內部使用了優(yōu)秀的架構設計和大量的設計模式,在我分析過Rtt最新版的源碼和大量優(yōu)秀的t源碼分析文章后,我發(fā)現,要想真正理解et?t內部的核心源碼流程和設計思想,首先,需要對它使用到的九大設計模式有一定的了解,下面我簡單說一說:1、創(chuàng)建Retro?t實例使用建造者模式通過內部Buer類建立了一個Rtoft網絡請求工廠使用了工廠方法模式。2、創(chuàng)建網絡請求接口的實接著,使用了建造者模式&單例模式創(chuàng)建了serviceMethod對象再者,使用了策略模式對serviceMethod對象進行網絡請求參數配置,即通過解析網絡請求接口方法的參數、返回值和注解類型,從Rt?t對象中獲取對應的網絡的url地址、網絡請求執(zhí)行器、網絡請求適配器和數據轉換器。最后,使用了裝飾者模式EctelBackserviceMethodHandr從子線程切換到主線程從而對返回數據結果進行處理。3、發(fā)送網絡請求在異步請求時,通過靜態(tài)delegate代理對網絡請求接口的方法中的每個參數使用對ParameterHanlder進行解析4、解析數5、切換線使用了適配器模式通過檢測不同的Plfrm使用不同的回調執(zhí)行器,然后使用回調執(zhí)行器切換線程,這里同樣是使用了裝飾模式。6、處理結Android:主流網絡請求開源庫的對比(Android-Async-Http、Volley、OkHttp、三、響應式編程框架:RxJava實現原RxJava變換操作符map?atMapconcatMapmap:【數據類型轉換】將被觀察者發(fā)送的事件轉換為另一種類型的事件?atMap:【化解循環(huán)嵌套和接口嵌套】將被觀察者發(fā)送的事件序列進行拆分&轉換后合并成一concatMap:【有序】與?atMap的區(qū)別在于,拆分&重新合并生成的事件序列的順序者舊序列生產的順序一致定期從被觀察者發(fā)送的事件中獲取一定數量的事件并放到緩存區(qū)中,然后把這些數據集合打包發(fā)射。RxJava中map和?atmap操作符的區(qū)別及底層實手寫rxjava遍歷數組你認為Rxjava的線程池與你們自己實現任務管理框架有什么區(qū)這個庫是做什么用的Glide是Android中的一個圖片加Glide是Android中的一個圖片加載庫,用于實現圖片加為什么要在項目中使用這個1、多樣化媒體加載:不僅可以進行圖片緩存,還支持Gif、WebP、縮略圖,甚至是Video2、通過設置綁定生命周期:可以使加載圖片的生命周期動態(tài)管理起3、高效的緩存策略:支持內存、isk緩存,并且Passo只會緩存原始尺寸的圖片,內Glie多種規(guī)格,也就是Glde會根據你Imageiw的大小來緩存相應大小的圖片尺寸。4、內存開銷小:默認的Bitmap格式是RGB_565格式,而Passo默認的是AGB_888小一半。這個庫都有哪些用法?對應什么樣的使用場4、可以配置磁盤緩存策略ALL、NONE、SOURCE、RESULT這個庫的優(yōu)缺點是什么,跟同類型庫的比庫比較大,源碼實現復這個庫的核心實現原理是什么?如果讓你實現這個庫的某些核心功能,你會考慮怎么去實設置請求url,并記錄url已設置的狀態(tài)3、2、遞歸建立縮略圖請求,沒有縮略圖請求,則直接進行正常請4、engine是一個負責加載和管理緩存資源常規(guī)三級緩存的流程:強引用->軟引用->硬盤緩當我們的APP中想要加載某張圖片時,先去ruace中尋找圖片,如果LruCche中有,則直接取出來使用,如果LrCache中沒有,則去Softefeece中尋找(軟引用適合當cache,當內存吃緊的時候才會被回收。而ekfeence在每次systc()就會被回收)(當ruaceSftefeee中),如果Sftefeee中有,則從Sftefeee中取出圖片使用,同時將圖片重新放回到rCache中,如果Sftefeee中也沒有圖片,則去硬盤緩存中中尋找,如果有則取出來使用,同時將圖片添加到rCache中,如果沒有,則連接網絡從網上下載圖片。圖片下載完成后,將圖片保存到硬盤緩存中,然后放到LrCace中。Glide的三層緩存機制Glide緩存機制Glide緩存機制大致分為三層:內存緩存、弱引用緩存、磁盤緩存的順序是:弱引用、內存、磁三層存儲的機制在Enie中實現的。先說下Enie是什么?Enie這一層負責加載時做管理內存緩存的邏輯。持有MryCache、M<K,efeEiRuc<?>>>。通過ad()來加載圖片,加載前后會做內存存儲的邏輯。如果內存緩存中沒有,那么才會使用Enob這一層來進行異步獲取硬盤資源或網絡資源。EeJob類似一個異步線程或bservable。Enie是一個全局唯一的,通過Gld.etEnie()來獲取。需要一個圖片資源,如果rache中有相應的資源圖片,那么就返回,同時從Lruche中清除,放到iveesouces中。ivesucesmp是盛放正在使用的資源,以弱引用的形式存在。同時資源內部有被引用的記錄。如果資源沒有引用記錄了,那么再放回Lrucce中,同時從iveesouces中清除。如果rache中沒有,就從activesuces中找,找到后相應資源引用加1。如果rache和iveesouces中沒有,那么進行資源異步請求(網絡/iskLrace),請求成功后,資源放到che和iveRouces中。Glide源碼機制的核心思使用一個弱引用mapivesuces來盛放項目中正在使用的資源。ucacheucache需要移除一個緩存時,會調用esouce.()方法。注意到該方法上面注釋寫著只有沒有任何consumer引用該資源的時候才可以調用這個方法。那么為什么調用esouce.()方法需要保證該資源沒有任何consumer引用呢?glideesouce定義的cyc()要做的事情是把這個不用的資源(假設是bmap或dwbe)放到btmapol中。btmapol是一個bmp回收再利用的庫,在做tnsform的時候會從這個btmpol中拿一個bmp進行再利用。這樣就避免了重新創(chuàng)建map,減少了內存的開支。而既然btmpol中的bmp會被重復利用,那么肯定要保證回收該資源的時候(即調用資源的cycle()時),要保證該資源真的沒有外界引用了。這也是為什么glide花費那么多邏輯來保證Lrucce中的資源沒有外界引用的原因。你從這個庫中學到什么有價值的或者說可借鑒的設計思Glide的高效的三層緩存機制,如圖片占用內存的計算公式:圖片高度*圖片寬度*一個像素占用的內存大小。所以,計算圖片占用內存大小的時候,要考慮圖片所在的目錄跟設備密度,這兩個因素其實影響的是圖片的寬高,anod會對圖片進行拉升跟壓縮。加載bitmap過程(怎樣保證不產生內存溢出由于Android對圖片使用內存有限制,若是加載幾兆的大圖片便內存溢出。Bitmap會將圖片的所有像(即長x寬)加載到內存中,如果圖片分辨率過大,會直接導致內存OOM,只有在BapFactry圖片時使用BtmpFactorOptns對相關參數進行配置來減少加載的像素。BitmapFactory.Options相關參數詳解(1).Options.inPreferredCon?g值來降低內存消耗比如:(1).Options.inPreferredCon?g值來降低內存消耗比如:默認值ARGB_8888改為RGB_565,節(jié)約一半內(2).設置Options.inSampleSize縮放比例,對大圖片進行壓縮(3).設置Options.inPurgeable和inInputShareable:讓系統能及時回收內(4).使用decodeStream代替decodeResource等其他方在Android應用的開發(fā)中,為了防止內存溢出,在處理一些占用內存大而且生命周期較長的對象時候,1、軟/弱引用可以和一個引用隊列(Reeu)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。利用這個隊列可以得知被回收的軟/弱引用的對象列表,從而為緩沖器清除已失效的軟/弱引用。2、如果只2、如果只是想避免OOM異常的發(fā)生,則可以使用軟引用。如果對于應用的性能更在意,想盡快3、可以根據對象是否經常使用來判斷選擇軟引用還是弱引用。如果該對象可能會經常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱引用。Android里的內存緩存和磁盤緩存是怎么實現的內存緩存基于LruCache實現,磁盤緩存基于DiskLruCache實現。這兩個類都基于Lru算法LinkedHashMap來實現LRU算法可以用一句話來描述,如下所RU是LetecntlyUsed的縮寫,最近最少使用算法,從它的名字就可以看出,它的核心原則是如果一個數據在最近一段時間沒有使用到,那么它在將來被訪問到的可能性也很小,則這類數據項會被優(yōu)先淘汰掉。LruCache原之前,我們會使用內存緩存技術實現,也就是軟引用或弱引用,在Android2.3(APILevel9)開始,垃其實LU緩存的實現類似于一個特殊的棧,把訪問過的元素放置到棧頂(若棧中存在,則更新至棧頂;若棧中不存在則直接入棧),然后如果棧中元素數量超過限定值,則刪除棧底元素(元素)。它的內部存在一個LinkedHashMap和maxSize,把最近使用的對象用強引用存儲在LinkedHashMap中,給出來put和get方法,每次put圖片時計算緩存中所有圖片的總大小,跟maxSize進行比較,大于maxSize,就將最久添加的圖片移除,反之小于maxSize就添加進來。rCache的原理就是利用dashMp持有對象的強引用,按照Lru算法進行對象淘汰。具體說來假設我們從表尾訪問數據,在表頭刪除數據,當訪問的數據項在鏈表中存在時,則將該數據項移動到表尾,否則在表尾新建一個數據項。當鏈表容量超過一定閾值,則移除表頭的數據。詳細來說就是rCache中維護了一個集合dHsMp,該ndashMap是以訪問順序排序的。當調用ut()方法時,就會在結合中添加元素,并調用trimoize()用ndHsMp的迭代器刪除隊頭元素,即近期最少訪問的元素。當調用et()方法訪問緩存對象時,就會調用dashMpet()方法獲得對應集合元素,同時會更新該元素到隊尾。LruCacheput方法核心在添加過緩存對象后,調用trimoSize()方法,來判斷緩存是否已滿,如果滿了就要刪除近期最少使用的對象。trimoSize()方法不斷地刪除indashMap中隊頭的元素,即近期最少訪問的,直到緩存大小小于最大值(mxSize)。LruCacheget方法核心邏當調用LrCace的et()方法獲取集合中的緩存對象時,就代表訪問了一次該元素,將會更新隊列,保持整個隊列是按照訪問順序排序的。為什么會選擇LinkedHashMap呢這跟LinkedHashMap的特性有關,LinkedHashMap的構造函數里有個布爾參數accessOrder,當它true時,LinkedHashMap會以訪問順序為序排列元素,否則以插入順序為序排序元LinkedHashMap原LinkedHashMap幾乎和HashMap一樣:從技術上來說,不同的是它定義了一個Entry<K,V>header,這個header不是放在Table里,它是額外獨立出來的。LinkedHashMap通過繼承hashMap中的Entry<K,V>,并添加兩個屬性Entry<K,V>before,after,和header結合起來組成一個雙向DisLruCache原DiskLruCache與LruCache原理相似,只是DisLruCache原DiskLruCache與LruCache原理相似,只是多了一個journal文件來做磁盤文件的管理,如下所11DIRTYCLEAN1517126350519REMOVE注:這里的緩存目錄是應用的緩存目錄et的手機可以通過以下命令進入到該目錄中或者將該目錄整體拷貝出來:我們來分析下這個文件的內第一行:lio.Diskuhe第二行:1,DkCe源碼版本號。第五行:空第六行及后續(xù)行:緩存操作記第六行及后續(xù)行表示緩存操作記錄,關于操作記錄,我們需要了解以下三DIRTY表示一個entry正在被寫入。寫入分兩種情況,如果成功會緊接著寫入一行CLEAN的記錄;如果當手動調用remove(key)方法的時候也會寫入一條REMOVE記錄READ就是說明有一次讀取的記CLEAN的后面還記錄了文件的長度,注意可能會一個key對應多個文件,那么就會有多個數Bitmap壓縮策加載Bitmap的方式BitmapFactory四類方decodeFile(文件系統)decodeResourece(資源)decodeStream(輸入流)BitmapFactory.options參數nSamlSze采樣率,對圖片高和寬進行縮放,以最小比進行縮放(一般取值為2的指數)常是根據圖片寬高實際的大小/需要的寬高大小,分別計算出寬和高的縮放比。但應該取其中最小的縮放比,避免縮放圖片太小,到達指定控件中不能鋪滿,需要拉伸從而導致模糊。adbshellrun-ascpadbbackupnoapkcom.your.packagenameinJustDecodeBounds獲取圖片的寬高信息,交給inSampleSize參數inJustDecodeBounds獲取圖片的寬高信息,交給inSampleSize參數選擇縮放比。通過inJustDecodeBounds=true,然后加載圖片就可以實現只解析圖片的寬高信息,并不會真正的加inJustDecodeBoundsfalse,再重新加載圖片,就可以加載縮放后的圖片。高效加載Bitmap的流程1、將BitmapFactory.Options的inJustDecodeBounds參數設為true并加載圖2、從B

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論