Android中高級面試題
1驶悟、Activity生命周期械媒?
onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()
2、Service生命周期瞳氓?
service啟動方式有兩種限嫌,一種是通過startService()方式進行啟動,另一種是通過bindService()方式進行啟動褪贵。不同的啟動方式他們的生命周期是不一樣.
通過startService()這種方式啟動的service掂之,生命周期是這樣:調(diào)用startService() --> onCreate()--> onStartConmon()--> onDestroy()。這種方式啟動的話脆丁,需要注意一下幾個問題板惑,第一:當(dāng)我們通過startService被調(diào)用以后,多次在調(diào)用startService(),onCreate()方法也只會被調(diào)用一次偎快,而onStartConmon()會被多次調(diào)用當(dāng)我們調(diào)用stopService()的時候冯乘,onDestroy()就會被調(diào)用,從而銷毀服務(wù)晒夹。第二:當(dāng)我們通過startService啟動時候裆馒,通過intent傳值,在onStartConmon()方法中獲取值的時候丐怯,一定要先判斷intent是否為null喷好。
通過bindService()方式進行綁定,這種方式綁定service读跷,生命周期走法:bindService-->onCreate()-->onBind()-->unBind()-->onDestroy()? bingservice 這種方式進行啟動service好處是更加便利activity中操作service梗搅,比如加入service中有幾個方法,a,b 效览,如果要在activity中調(diào)用无切,在需要在activity獲取ServiceConnection對象,通過ServiceConnection來獲取service中內(nèi)部類的類對象丐枉,然后通過這個類對象就可以調(diào)用類中的方法哆键,當(dāng)然這個類需要繼承Binder對象
3、Activity的啟動過程(不要回答生命周期)
app啟動的過程有兩種情況瘦锹,第一種是從桌面launcher上點擊相應(yīng)的應(yīng)用圖標籍嘹,第二種是在activity中通過調(diào)用startActivity來啟動一個新的activity。
我們創(chuàng)建一個新的項目弯院,默認的根activity都是MainActivity辱士,而所有的activity都是保存在堆棧中的,我們啟動一個新的activity就會放在上一個activity上面听绳,而我們從桌面點擊應(yīng)用圖標的時候颂碘,由于launcher本身也是一個應(yīng)用,當(dāng)我們點擊圖標的時候辫红,系統(tǒng)就會調(diào)用startActivitySately(),一般情況下凭涂,我們所啟動的activity的相關(guān)信息都會保存在intent中祝辣,比如action,category等等切油。我們在安裝這個應(yīng)用的時候蝙斜,系統(tǒng)也會啟動一個PackaManagerService的管理服務(wù),這個管理服務(wù)會對AndroidManifest.xml文件進行解析澎胡,從而得到應(yīng)用程序中的相關(guān)信息孕荠,比如service,activity攻谁,Broadcast等等稚伍,然后獲得相關(guān)組件的信息。當(dāng)我們點擊應(yīng)用圖標的時候戚宦,就會調(diào)用startActivitySately()方法个曙,而這個方法內(nèi)部則是調(diào)用startActivty(),而startActivity()方法最終還是會調(diào)用startActivityForResult()這個方法。而在startActivityForResult()這個方法受楼。因為startActivityForResult()方法是有返回結(jié)果的垦搬,所以系統(tǒng)就直接給一個-1,就表示不需要結(jié)果返回了艳汽。而startActivityForResult()這個方法實際是通過Instrumentation類中的execStartActivity()方法來啟動activity猴贰,Instrumentation這個類主要作用就是監(jiān)控程序和系統(tǒng)之間的交互。而在這個execStartActivity()方法中會獲取ActivityManagerService的代理對象河狐,通過這個代理對象進行啟動activity米绕。啟動會就會調(diào)用一個checkStartActivityResult()方法,如果說沒有在配置清單中配置有這個組件馋艺,就會在這個方法中拋出異常了栅干。當(dāng)然最后是調(diào)用的是Application.scheduleLaunchActivity()進行啟動activity,而這個方法中通過獲取得到一個ActivityClientRecord對象丈钙,而這個ActivityClientRecord通過handler來進行消息的發(fā)送非驮,系統(tǒng)內(nèi)部會將每一個activity組件使用ActivityClientRecord對象來進行描述,而ActivityClientRecord對象中保存有一個LoaderApk對象雏赦,通過這個對象調(diào)用handleLaunchActivity來啟動activity組件,而頁面的生命周期方法也就是在這個方法中進行調(diào)用芙扎。
4星岗、Broadcast注冊方式與區(qū)別
此處延伸:什么情況下用動態(tài)注冊
Broadcast廣播,注冊方式主要有兩種.
第一種是靜態(tài)注冊戒洼,也可成為常駐型廣播俏橘,這種廣播需要在Androidmanifest.xml中進行注冊,這中方式注冊的廣播圈浇,不受頁面生命周期的影響寥掐,即使退出了頁面靴寂,也可以收到廣播這種廣播一般用于想開機自啟動啊等等,由于這種注冊的方式的廣播是常駐型廣播召耘,所以會占用CPU的資源百炬。
第二種是動態(tài)注冊,而動態(tài)注冊的話污它,是在代碼中注冊的剖踊,這種注冊方式也叫非常駐型廣播,收到生命周期的影響衫贬,退出頁面后德澈,就不會收到廣播,我們通常運用在更新UI方面固惯。這種注冊方式優(yōu)先級較高梆造。最后需要解綁,否會會內(nèi)存泄露
廣播是分為有序廣播和無序廣播葬毫。
5镇辉、HttpClient與HttpUrlConnection的區(qū)別
此處延伸:Volley里用的哪種請求方式(2.3前HttpClient,2.3后HttpUrlConnection)
首先HttpClient和HttpUrlConnection 這兩種方式都支持Https協(xié)議供常,都是以流的形式進行上傳或者下載數(shù)據(jù)摊聋,也可以說是以流的形式進行數(shù)據(jù)的傳輸,還有ipv6,以及連接池等功能栈暇。HttpClient這個擁有非常多的API麻裁,所以如果想要進行擴展的話,并且不破壞它的兼容性的話源祈,很難進行擴展煎源,也就是這個原因,Google在Android6.0的時候香缺,直接就棄用了這個HttpClient.
而HttpUrlConnection相對來說就是比較輕量級了手销,API比較少,容易擴展图张,并且能夠滿足Android大部分的數(shù)據(jù)傳輸锋拖。比較經(jīng)典的一個框架volley,在2.3版本以前都是使用HttpClient,在2.3以后就使用了HttpUrlConnection祸轮。
6兽埃、java虛擬機和Dalvik虛擬機的區(qū)別
Java虛擬機:
1、java虛擬機基于棧适袜。?基于棧的機器必須使用指令來載入和操作棧上數(shù)據(jù)柄错,所需指令更多更多。
2、java虛擬機運行的是java字節(jié)碼售貌。(java類會被編譯成一個或多個字節(jié)碼.class文件)
Dalvik虛擬機:
1给猾、dalvik虛擬機是基于寄存器的
2、Dalvik運行的是自定義的.dex字節(jié)碼格式颂跨。(java類被編譯成.class文件后敢伸,會通過一個dx工具將所有的.class文件轉(zhuǎn)換成一個.dex文件,然后dalvik虛擬機會從其中讀取指令和數(shù)據(jù)
3毫捣、常量池已被修改為只使用32位的索引详拙,以 簡化解釋器。
4蔓同、一個應(yīng)用饶辙,一個虛擬機實例,一個進程(所有android應(yīng)用的線程都是對應(yīng)一個linux線程斑粱,都運行在自己的沙盒中弃揽,不同的應(yīng)用在不同的進程中運行。每個android dalvik應(yīng)用程序都被賦予了一個獨立的linux PID(app_*))
7则北、進程笨笪ⅲ活(不死進程)
此處延伸:進程的優(yōu)先級是什么
當(dāng)前業(yè)界的Android進程保活手段主要分為** 黑尚揣、白涌矢、灰 **三種,其大致的實現(xiàn)思路如下:
黑色笨炱活:不同的app進程娜庇,用廣播相互喚醒(包括利用系統(tǒng)提供的廣播進行喚醒)
白色保活:啟動前臺Service
灰色狈嚼海活:利用系統(tǒng)的漏洞啟動前臺Service
黑色泵悖活
所謂黑色保活藕溅,就是利用不同的app進程使用廣播來進行相互喚醒匕得。舉個3個比較常見的場景:
場景1:開機,網(wǎng)絡(luò)切換巾表、拍照汁掠、拍視頻時候,利用系統(tǒng)產(chǎn)生的廣播喚醒app
場景2:接入第三方SDK也會喚醒相應(yīng)的app進程集币,如微信sdk會喚醒微信调塌,支付寶sdk會喚醒支付寶。由此發(fā)散開去惠猿,就會直接觸發(fā)了下面的 場景3
場景3:假如你手機里裝了支付寶、淘寶、天貓偶妖、UC等阿里系的app姜凄,那么你打開任意一個阿里系的app后,有可能就順便把其他阿里系的app給喚醒了趾访。(只是拿阿里打個比方态秧,其實BAT系都差不多)
白色保活
白色倍笮活手段非常簡單申鱼,就是調(diào)用系統(tǒng)api啟動一個前臺的Service進程,這樣會在系統(tǒng)的通知欄生成一個Notification云头,用來讓用戶知道有這樣一個app在運行著捐友,哪怕當(dāng)前的app退到了后臺。如下方的LBE和QQ音樂這樣:
灰色崩;保活
灰色毕蛔活,這種被璧危活手段是應(yīng)用范圍最廣泛猴鲫。它是利用系統(tǒng)的漏洞來啟動一個前臺的Service進程,與普通的啟動方式區(qū)別在于谣殊,它不會在系統(tǒng)通知欄處出現(xiàn)一個Notification拂共,看起來就如同運行著一個后臺Service進程一樣。這樣做帶來的好處就是姻几,用戶無法察覺到你運行著一個前臺進程(因為看不到Notification),但你的進程優(yōu)先級又是高于普通后臺進程的宜狐。那么如何利用系統(tǒng)的漏洞呢,大致的實現(xiàn)思路和代碼如下:
思路一:API < 18鲜棠,啟動前臺Service時直接傳入new Notification()肌厨;
思路二:API >= 18,同時啟動兩個id相同的前臺Service豁陆,然后再將后啟動的Service做stop處理
熟悉Android系統(tǒng)的童鞋都知道柑爸,系統(tǒng)出于體驗和性能上的考慮,app在退到后臺時系統(tǒng)并不會真正的kill掉這個進程盒音,而是將其緩存起來表鳍。打開的應(yīng)用越多,后臺緩存的進程也越多祥诽。在系統(tǒng)內(nèi)存不足的情況下譬圣,系統(tǒng)開始依據(jù)自身的一套進程回收機制來判斷要kill掉哪些進程,以騰出內(nèi)存來供給需要的app雄坪。這套殺進程回收內(nèi)存的機制就叫 Low Memory Killer 厘熟,它是基于Linux內(nèi)核的 OOM Killer(Out-Of-Memory killer)機制誕生。
進程的重要性,劃分5級:
前臺進程(Foreground process)
可見進程(Visible process)
服務(wù)進程(Service process)
后臺進程(Background process)
空進程(Empty process)
了解完Low Memory Killer绳姨,再科普一下oom_adj登澜。什么是oom_adj?它是linux內(nèi)核分配給每個系統(tǒng)進程的一個值飘庄,代表進程的優(yōu)先級脑蠕,進程回收機制就是根據(jù)這個優(yōu)先級來決定是否進行回收。對于oom_adj的作用跪削,你只需要記住以下幾點即可:
進程的oom_adj越大谴仙,表示此進程優(yōu)先級越低,越容易被殺回收碾盐;越小晃跺,表示進程優(yōu)先級越高,越不容易被殺回收
普通app進程的oom_adj>=0,系統(tǒng)進程的oom_adj才可能<0
有些手機廠商把這些知名的app放入了自己的白名單中廓旬,保證了進程不死來提高用戶體驗(如微信哼审、QQ、陌陌都在小米的白名單中)孕豹。如果從白名單中移除涩盾,他們終究還是和普通app一樣躲避不了被殺的命運,為了盡量避免被殺励背,還是老老實實去做好優(yōu)化工作吧春霍。
所以,進程币睹迹活的根本方案終究還是回到了性能優(yōu)化上址儒,進程永生不死終究是個徹頭徹尾的偽命題!
8衅疙、講解一下Context
Context是一個抽象基類莲趣。在翻譯為上下文,也可以理解為環(huán)境饱溢,是提供一些程序的運行環(huán)境基礎(chǔ)信息喧伞。Context下有兩個子類,ContextWrapper是上下文功能的封裝類绩郎,而ContextImpl則是上下文功能的實現(xiàn)類潘鲫。而ContextWrapper又有三個直接的子類, ContextThemeWrapper肋杖、Service和Application溉仑。其中,ContextThemeWrapper是一個帶主題的封裝類状植,而它有一個直接子類就是Activity浊竟,所以Activity和Service以及Application的Context是不一樣的怨喘,只有Activity需要主題,Service不需要主題逐沙。Context一共有三種類型哲思,分別是Application、Activity和Service吩案。這三個類雖然分別各種承擔(dān)著不同的作用,但它們都屬于Context的一種帝簇,而它們具體Context的功能則是由ContextImpl類去實現(xiàn)的徘郭,因此在絕大多數(shù)場景下,Activity丧肴、Service和Application這三種類型的Context都是可以通用的残揉。不過有幾種場景比較特殊,比如啟動Activity芋浮,還有彈出Dialog。出于安全原因的考慮,Android是不允許Activity或Dialog憑空出現(xiàn)的燕侠,一個Activity的啟動必須要建立在另一個Activity的基礎(chǔ)之上厉萝,也就是以此形成的返回棧。而Dialog則必須在一個Activity上面彈出(除非是System Alert類型的Dialog)瘤旨,因此在這種場景下梯啤,我們只能使用Activity類型的Context,否則將會出錯存哲。
getApplicationContext()和getApplication()方法得到的對象都是同一個application對象因宇,只是對象的類型不一樣。
Context數(shù)量 = Activity數(shù)量 + Service數(shù)量 + 1 (1為Application)
9祟偷、理解Activity察滑,View,Window三者關(guān)系
這個問題真的很不好回答。所以這里先來個算是比較恰當(dāng)?shù)谋扔鱽硇稳菹滤鼈兊年P(guān)系吧修肠。Activity像一個工匠(控制單元)贺辰,Window像窗戶(承載模型),View像窗花(顯示視圖)LayoutInflater像剪刀氛赐,Xml配置像窗花圖紙魂爪。
1:Activity構(gòu)造的時候會初始化一個Window,準確的說是PhoneWindow艰管。
2:這個PhoneWindow有一個“ViewRoot”滓侍,這個“ViewRoot”是一個View或者說ViewGroup,是最初始的根視圖牲芋。
3:“ViewRoot”通過addView方法來一個個的添加View撩笆。比如TextView捺球,Button等
4:這些View的事件監(jiān)聽,是由WindowManagerService來接受消息夕冲,并且回調(diào)Activity函數(shù)氮兵。比如onClickListener,onKeyDown等歹鱼。
10泣栈、四種LaunchMode及其使用場景
此處延伸:棧(First In Last Out)與隊列(First In First Out)的區(qū)別
棧與隊列的區(qū)別:
1.隊列先進先出,棧先進后出
2.對插入和刪除操作的"限定"弥姻。 棧是限定只能在表的一端進行插入和刪除操作的線性表南片。 隊列是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。
3.遍歷數(shù)據(jù)速度不同
standard模式
這是默認模式庭敦,每次激活A(yù)ctivity時都會創(chuàng)建Activity實例疼进,并放入任務(wù)棧中。使用場景:大多數(shù)Activity秧廉。
singleTop模式
如果在任務(wù)的棧頂正好存在該Activity的實例伞广,就重用該實例( 會調(diào)用實例的 onNewIntent() ),否則就會創(chuàng)建新的實例并放入棧頂疼电,即使棧中已經(jīng)存在該Activity的實例嚼锄,只要不在棧頂,都會創(chuàng)建新的實例澜沟。使用場景如新聞類或者閱讀類App的內(nèi)容頁面灾票。
singleTask模式
如果在棧中已經(jīng)有該Activity的實例,就重用該實例(會調(diào)用實例的 onNewIntent() )茫虽。重用時刊苍,會讓該實例回到棧頂,因此在它上面的實例將會被移出棧濒析。如果棧中不存在該實例正什,將會創(chuàng)建新的實例放入棧中。使用場景如瀏覽器的主界面号杏。不管從多少個應(yīng)用啟動瀏覽器婴氮,只會啟動主界面一次,其余情況都會走onNewIntent盾致,并且會清空主界面上面的其他頁面主经。
singleInstance模式
在一個新棧中創(chuàng)建該Activity的實例,并讓多個應(yīng)用共享該棧中的該Activity實例庭惜。一旦該模式的Activity實例已經(jīng)存在于某個棧中罩驻,任何應(yīng)用再激活該Activity時都會重用該棧中的實例( 會調(diào)用實例的 onNewIntent() )。其效果相當(dāng)于多個應(yīng)用共享一個應(yīng)用护赊,不管誰激活該 Activity 都會進入同一個應(yīng)用中惠遏。使用場景如鬧鈴提醒砾跃,將鬧鈴提醒與鬧鈴設(shè)置分離。singleInstance不要用于中間頁面节吮,如果用于中間頁面抽高,跳轉(zhuǎn)會有問題,比如:A -> B (singleInstance) -> C透绩,完全退出后翘骂,在此啟動,首先打開的是B渺贤。
11雏胃、View的繪制流程
自定義控件:
1、組合控件志鞍。這種自定義控件不需要我們自己繪制,而是使用原生控件組合成的新控件方仿。如標題欄固棚。
2、繼承原有的控件仙蚜。這種自定義控件在原生控件提供的方法外此洲,可以自己添加一些方法。如制作圓角委粉,圓形圖片呜师。
3、完全自定義控件:這個View上所展現(xiàn)的內(nèi)容全部都是我們自己繪制出來的贾节。比如說制作水波紋進度條汁汗。
View的繪制流程:OnMeasure()——>OnLayout()——>OnDraw()
第一步:OnMeasure():測量視圖大小。從頂層父View到子View遞歸調(diào)用measure方法栗涂,measure方法又回調(diào)OnMeasure知牌。
第二步:OnLayout():確定View位置,進行頁面布局斤程。從頂層父View向子View的遞歸調(diào)用view.layout方法的過程角寸,即父View根據(jù)上一步measure子View所得到的布局大小和布局參數(shù),將子View放在合適的位置上忿墅。
第三步:OnDraw():繪制視圖扁藕。ViewRoot創(chuàng)建一個Canvas對象,然后調(diào)用OnDraw()疚脐。六個步驟:①亿柑、繪制視圖的背景;②亮曹、保存畫布的圖層(Layer)橄杨;③秘症、繪制View的內(nèi)容;④式矫、繪制View子視圖乡摹,如果沒有就不用;
⑤采转、還原圖層(Layer)聪廉;⑥、繪制滾動條故慈。
12板熊、View,ViewGroup事件分發(fā)
1. Touch事件分發(fā)中只有兩個主角:ViewGroup和View察绷。ViewGroup包含onInterceptTouchEvent干签、dispatchTouchEvent、onTouchEvent三個相關(guān)事件拆撼。View包含dispatchTouchEvent容劳、onTouchEvent兩個相關(guān)事件。其中ViewGroup又繼承于View闸度。
2.ViewGroup和View組成了一個樹狀結(jié)構(gòu)竭贩,根節(jié)點為Activity內(nèi)部包含的一個ViwGroup。
3.觸摸事件由Action_Down莺禁、Action_Move留量、Aciton_UP組成,其中一次完整的觸摸事件中哟冬,Down和Up都只有一個楼熄,Move有若干個,可以為0個柒傻。
4.當(dāng)Acitivty接收到Touch事件時孝赫,將遍歷子View進行Down事件的分發(fā)。ViewGroup的遍歷可以看成是遞歸的红符。分發(fā)的目的是為了找到真正要處理本次完整觸摸事件的View青柄,這個View會在onTouchuEvent結(jié)果返回true。
5.當(dāng)某個子View返回true時预侯,會中止Down事件的分發(fā)致开,同時在ViewGroup中記錄該子View。接下去的Move和Up事件將由該子View直接進行處理萎馅。由于子View是保存在ViewGroup中的双戳,多層ViewGroup的節(jié)點結(jié)構(gòu)時,上級ViewGroup保存的會是真實處理事件的View所在的ViewGroup對象:如ViewGroup0-ViewGroup1-TextView的結(jié)構(gòu)中糜芳,TextView返回了true飒货,它將被保存在ViewGroup1中魄衅,而ViewGroup1也會返回true,被保存在ViewGroup0中塘辅。當(dāng)Move和UP事件來時晃虫,會先從ViewGroup0傳遞至ViewGroup1,再由ViewGroup1傳遞至TextView扣墩。
6.當(dāng)ViewGroup中所有子View都不捕獲Down事件時哲银,將觸發(fā)ViewGroup自身的onTouch事件。觸發(fā)的方式是調(diào)用super.dispatchTouchEvent函數(shù)呻惕,即父類View的dispatchTouchEvent方法荆责。在所有子View都不處理的情況下,觸發(fā)Acitivity的onTouchEvent方法亚脆。
7.onInterceptTouchEvent有兩個作用:1.攔截Down事件的分發(fā)做院。2.中止Up和Move事件向目標View傳遞,使得目標View所在的ViewGroup捕獲Up和Move事件濒持。
13山憨、保存Activity狀態(tài)
onSaveInstanceState(Bundle)會在activity轉(zhuǎn)入后臺狀態(tài)之前被調(diào)用,也就是onStop()方法之前弥喉,onPause方法之后被調(diào)用;
14玛迄、Android中的幾種動畫
幀動畫:指通過指定每一幀的圖片和播放時間由境,有序的進行播放而形成動畫效果,比如想聽的律動條蓖议。
補間動畫:指通過指定View的初始狀態(tài)虏杰、變化時間、方式勒虾,通過一系列的算法去進行圖形變換纺阔,從而形成動畫效果,主要有Alpha修然、Scale笛钝、Translate、Rotate四種效果愕宋。注意:只是在視圖層實現(xiàn)了動畫效果玻靡,并沒有真正改變View的屬性,比如滑動列表中贝,改變標題欄的透明度囤捻。
屬性動畫:在Android3.0的時候才支持,通過不斷的改變View的屬性邻寿,不斷的重繪而形成動畫效果蝎土。相比于視圖動畫视哑,View的屬性是真正改變了。比如view的旋轉(zhuǎn)誊涯,放大挡毅,縮小。
15醋拧、Android中跨進程通訊的幾種方式
Android跨進程通信慷嗜,像intent,contentProvider,廣播丹壕,service都可以跨進程通信庆械。
intent:這種跨進程方式并不是訪問內(nèi)存的形式,它需要傳遞一個uri,比如說打電話菌赖。
contentProvider:這種形式缭乘,是使用數(shù)據(jù)共享的形式進行數(shù)據(jù)共享。
service:遠程服務(wù)琉用,aidl
廣播
16堕绩、AIDL理解
此處延伸:簡述Binder
AIDL:每一個進程都有自己的Dalvik VM實例,都有自己的一塊獨立的內(nèi)存邑时,都在自己的內(nèi)存上存儲自己的數(shù)據(jù)奴紧,執(zhí)行著自己的操作,都在自己的那片狹小的空間里過完自己的一生晶丘。而aidl就類似與兩個進程之間的橋梁黍氮,使得兩個進程之間可以進行數(shù)據(jù)的傳輸,跨進程通信有多種選擇浅浮,比如 BroadcastReceiver , Messenger 等沫浆,但是 BroadcastReceiver 占用的系統(tǒng)資源比較多,如果是頻繁的跨進程通信的話顯然是不可取的滚秩;Messenger 進行跨進程通信時請求隊列是同步進行的专执,無法并發(fā)執(zhí)行。
Binde機制簡單理解:
在Android系統(tǒng)的Binder機制中郁油,是有Client,Service,ServiceManager,Binder驅(qū)動程序組成的本股,其中Client,service已艰,Service Manager運行在用戶空間痊末,Binder驅(qū)動程序是運行在內(nèi)核空間的。而Binder就是把這4種組件粘合在一塊的粘合劑哩掺,其中核心的組件就是Binder驅(qū)動程序凿叠,Service Manager提供輔助管理的功能,而Client和Service正是在Binder驅(qū)動程序和Service Manager提供的基礎(chǔ)設(shè)施上實現(xiàn)C/S 之間的通信。其中Binder驅(qū)動程序提供設(shè)備文件/dev/binder與用戶控件進行交互盒件,
Client蹬碧、Service,Service Manager通過open和ioctl文件操作相應(yīng)的方法與Binder驅(qū)動程序進行通信炒刁。而Client和Service之間的進程間通信是通過Binder驅(qū)動程序間接實現(xiàn)的恩沽。而Binder Manager是一個守護進程,用來管理Service翔始,并向Client提供查詢Service接口的能力罗心。
17、Handler的原理
Android中主線程是不能進行耗時操作的城瞎,子線程是不能進行更新UI的渤闷。所以就有了handler,它的作用就是實現(xiàn)線程之間的通信脖镀。
handler整個流程中飒箭,主要有四個對象,handler蜒灰,Message,MessageQueue,Looper弦蹂。當(dāng)應(yīng)用創(chuàng)建的時候,就會在主線程中創(chuàng)建handler對象强窖,
我們通過要傳送的消息保存到Message中凸椿,handler通過調(diào)用sendMessage方法將Message發(fā)送到MessageQueue中,Looper對象就會不斷的調(diào)用loop()方法
不斷的從MessageQueue中取出Message交給handler進行處理翅溺。從而實現(xiàn)線程之間的通信削饵。
18、Binder機制原理
在Android系統(tǒng)的Binder機制中未巫,是有Client,Service,ServiceManager,Binder驅(qū)動程序組成的,其中Client启昧,service叙凡,Service Manager運行在用戶空間,Binder驅(qū)動程序是運行在內(nèi)核空間的密末。而Binder就是把這4種組件粘合在一塊的粘合劑握爷,其中核心的組件就是Binder驅(qū)動程序,Service Manager提供輔助管理的功能严里,而Client和Service正是在Binder驅(qū)動程序和Service Manager提供的基礎(chǔ)設(shè)施上實現(xiàn)C/S 之間的通信新啼。其中Binder驅(qū)動程序提供設(shè)備文件/dev/binder與用戶控件進行交互,Client刹碾、Service燥撞,Service Manager通過open和ioctl文件操作相應(yīng)的方法與Binder驅(qū)動程序進行通信。而Client和Service之間的進程間通信是通過Binder驅(qū)動程序間接實現(xiàn)的。而Binder Manager是一個守護進程物舒,用來管理Service色洞,并向Client提供查詢Service接口的能力。
19冠胯、熱修復(fù)的原理
我們知道Java虛擬機 —— JVM 是加載類的class文件的火诸,而Android虛擬機——Dalvik/ART VM 是加載類的dex文件,
而他們加載類的時候都需要ClassLoader,ClassLoader有一個子類BaseDexClassLoader荠察,而BaseDexClassLoader下有一個
數(shù)組——DexPathList置蜀,是用來存放dex文件,當(dāng)BaseDexClassLoader通過調(diào)用findClass方法時悉盆,實際上就是遍歷數(shù)組盯荤,
找到相應(yīng)的dex文件,找到舀瓢,則直接將它return廷雅。而熱修復(fù)的解決方法就是將新的dex添加到該集合中,并且是在舊的dex的前面京髓,
所以就會優(yōu)先被取出來并且return返回航缀。
20、Android內(nèi)存泄露及管理
(1)內(nèi)存溢出(OOM)和內(nèi)存泄露(對象無法被回收)的區(qū)別堰怨。
(2)引起內(nèi)存泄露的原因
(3)內(nèi)存泄露檢測工具 ------>LeakCanary
內(nèi)存溢出out of memory:是指程序在申請內(nèi)存時芥玉,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory备图;比如申請了一個integer,但給它存了long才能存下的數(shù)灿巧,那就是內(nèi)存溢出。內(nèi)存溢出通俗的講就是內(nèi)存不夠用揽涮。
內(nèi)存泄露memory leak:是指程序在申請內(nèi)存后抠藕,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略蒋困,但內(nèi)存泄露堆積后果很嚴重盾似,無論多少內(nèi)存,遲早會被占光
內(nèi)存泄露原因:
一、Handler引起的內(nèi)存泄漏雪标。
解決:將Handler聲明為靜態(tài)內(nèi)部類零院,就不會持有外部類SecondActivity的引用,其生命周期就和外部類無關(guān)村刨,
如果Handler里面需要context的話告抄,可以通過弱引用方式引用外部類
二、單例模式引起的內(nèi)存泄漏嵌牺。
解決:Context是ApplicationContext打洼,由于ApplicationContext的生命周期是和app一致的龄糊,不會導(dǎo)致內(nèi)存泄漏
三、非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實例引起的內(nèi)存泄漏拟蜻。
解決:把內(nèi)部類修改為靜態(tài)的就可以避免內(nèi)存泄漏了
四绎签、非靜態(tài)匿名內(nèi)部類引起的內(nèi)存泄漏。
解決:將匿名內(nèi)部類設(shè)置為靜態(tài)的酝锅。
五诡必、注冊/反注冊未成對使用引起的內(nèi)存泄漏。
注冊廣播接受器搔扁、EventBus等爸舒,記得解綁。
六稿蹲、資源對象沒有關(guān)閉引起的內(nèi)存泄漏扭勉。
在這些資源不使用的時候,記得調(diào)用相應(yīng)的類似close()苛聘、destroy()涂炎、recycler()、release()等方法釋放设哗。
七唱捣、集合對象沒有及時清理引起的內(nèi)存泄漏。
通常會把一些對象裝入到集合中网梢,當(dāng)不使用的時候一定要記得及時清理集合震缭,讓相關(guān)對象不再被引用。
21战虏、Fragment與Fragment拣宰、Activity通信的方式
1.直接在一個Fragment中調(diào)用另外一個Fragment中的方法
2.使用接口回調(diào)
3.使用廣播
4.Fragment直接調(diào)用Activity中的public方法
22、Android UI適配
字體使用sp,使用dp烦感,多使用match_parent巡社,wrap_content,weight
圖片資源手趣,不同圖片的的分辨率重贺,放在相應(yīng)的文件夾下可使用百分比代替。
23回懦、app優(yōu)化
app優(yōu)化:(工具:Hierarchy Viewer 分析布局? 工具:TraceView 測試分析耗時的)
App啟動優(yōu)化
布局優(yōu)化
響應(yīng)優(yōu)化
內(nèi)存優(yōu)化
電池使用優(yōu)化
網(wǎng)絡(luò)優(yōu)化
App啟動優(yōu)化(針對冷啟動)
App啟動的方式有三種:
冷啟動:App沒有啟動過或App進程被killed, 系統(tǒng)中不存在該App進程, 此時啟動App即為冷啟動。
熱啟動:熱啟動意味著你的App進程只是處于后臺, 系統(tǒng)只是將其從后臺帶到前臺, 展示給用戶次企。
介于冷啟動和熱啟動之間,一般來說在以下兩種情況下發(fā)生:
(1)用戶back退出了App, 然后又啟動. App進程可能還在運行, 但是activity需要重建怯晕。
(2)用戶退出App后, 系統(tǒng)可能由于內(nèi)存原因?qū)pp殺死, 進程和activity都需要重啟, 但是可以在onCreate中將被動殺死鎖保存的狀態(tài)(saved instance state)恢復(fù)。
優(yōu)化:
Application的onCreate(特別是第三方SDK初始化)缸棵,首屏Activity的渲染都不要進行耗時操作舟茶,如果有,就可以放到子線程或者IntentService中
布局優(yōu)化
盡量不要過于復(fù)雜的嵌套“闪梗可以使用隧出,,
響應(yīng)優(yōu)化
Android系統(tǒng)每隔16ms會發(fā)出VSYNC信號重繪我們的界面(Activity)阀捅。
頁面卡頓的原因:
(1)過于復(fù)雜的布局.
(2)UI線程的復(fù)雜運算
(3)頻繁的GC,導(dǎo)致頻繁GC有兩個原因:1胀瞪、內(nèi)存抖動, 即大量的對象被創(chuàng)建又在短時間內(nèi)馬上被釋放.2、瞬間產(chǎn)生大量的對象會嚴重占用內(nèi)存區(qū)域饲鄙。
內(nèi)存優(yōu)化:參考內(nèi)存泄露和內(nèi)存溢出部分
電池使用優(yōu)化(使用工具:Batterystats & bugreport)
(1)優(yōu)化網(wǎng)絡(luò)請求
(2)定位中使用GPS, 請記得及時關(guān)閉
網(wǎng)絡(luò)優(yōu)化(網(wǎng)絡(luò)連接對用戶的影響:流量,電量,用戶等待)可在Android studio下方logcat旁邊那個工具Network Monitor檢測
API設(shè)計:App與Server之間的API設(shè)計要考慮網(wǎng)絡(luò)請求的頻次, 資源的狀態(tài)等. 以便App可以以較少的請求來完成業(yè)務(wù)需求和界面的展示.
Gzip壓縮:使用Gzip來壓縮request和response, 減少傳輸數(shù)據(jù)量, 從而減少流量消耗.
圖片的Size:可以在獲取圖片時告知服務(wù)器需要的圖片的寬高, 以便服務(wù)器給出合適的圖片, 避免浪費.
網(wǎng)絡(luò)緩存:適當(dāng)?shù)木彺?既可以讓我們的應(yīng)用看起來更快, 也能避免一些不必要的流量消耗.
24凄诞、圖片優(yōu)化
(1)對圖片本身進行操作。盡量不要使用setImageBitmap忍级、setImageResource帆谍、BitmapFactory.decodeResource來設(shè)置一張大圖,因為這些方法在完成decode后轴咱,
最終都是通過java層的createBitmap來完成的汛蝙,需要消耗更多內(nèi)存.
(2)圖片進行縮放的比例,SDK中建議其值是2的指數(shù)值,值越大會導(dǎo)致圖片不清晰朴肺。
(3)不用的圖片記得調(diào)用圖片的recycle()方法
25窖剑、HybridApp WebView和JS交互
Android與JS通過WebView互相調(diào)用方法,實際上是:
Android去調(diào)用JS的代碼
1.通過WebView的loadUrl(),使用該方法比較簡潔宇挫,方便苛吱。但是效率比較低,獲取返回值比較困難器瘪。
2.通過WebView的evaluateJavascript(),該方法效率高翠储,但是4.4以上的版本才支持,4.4以下版本不支持橡疼。所以建議兩者混合使用援所。
JS去調(diào)用Android的代碼
1.通過WebView的addJavascriptInterface()進行對象映射 ,該方法使用簡單欣除,僅將Android對象和JS對象映射即可住拭,但是存在比較大的漏洞。
漏洞產(chǎn)生原因是:當(dāng)JS拿到Android這個對象后历帚,就可以調(diào)用這個Android對象中所有的方法滔岳,包括系統(tǒng)類(java.lang.Runtime 類),從而進行任意代碼執(zhí)行挽牢。
解決方式:
(1)Google在Android 4.2 版本中規(guī)定對被調(diào)用的函數(shù)以 @JavascriptInterface進行注解從而避免漏洞攻擊谱煤。
(2)在Android 4.2版本之前采用攔截prompt()進行漏洞修復(fù)。
2.通過 WebViewClient 的shouldOverrideUrlLoading ()方法回調(diào)攔截 url 禽拔。這種方式的優(yōu)點:不存在方式1的漏洞刘离;缺點:JS獲取Android方法的返回值復(fù)雜室叉。(ios主要用的是這個方式)
(1)Android通過 WebViewClient 的回調(diào)方法shouldOverrideUrlLoading ()攔截 url
(2)解析該 url 的協(xié)議
(3)如果檢測到是預(yù)先約定好的協(xié)議,就調(diào)用相應(yīng)方法
3.通過 WebChromeClient 的onJsAlert()硫惕、onJsConfirm()茧痕、onJsPrompt()方法回調(diào)攔截JS對話框alert()、confirm()恼除、prompt() 消息
這種方式的優(yōu)點:不存在方式1的漏洞踪旷;缺點:JS獲取Android方法的返回值復(fù)雜。
26缚柳、JAVA GC原理
垃圾收集算法的核心思想是:對虛擬機可用內(nèi)存空間埃脏,即堆空間中的對象進行識別,如果對象正在被引用秋忙,那么稱其為存活對象
彩掐,反之,如果對象不再被引用灰追,則為垃圾對象堵幽,可以回收其占據(jù)的空間,用于再分配弹澎。垃圾收集算法的選擇和垃圾收集系統(tǒng)參數(shù)的合理調(diào)節(jié)直接影響著系統(tǒng)性能朴下。
27、ANR
ANR全名Application Not Responding, 也就是"應(yīng)用無響應(yīng)". 當(dāng)操作在一段時間內(nèi)系統(tǒng)無法處理時, 系統(tǒng)層面會彈出上圖那樣的ANR對話框.
產(chǎn)生原因:
(1)5s內(nèi)無法響應(yīng)用戶輸入事件(例如鍵盤輸入, 觸摸屏幕等).
(2)BroadcastReceiver在10s內(nèi)無法結(jié)束
(3)Service 20s內(nèi)無法結(jié)束(低概率)
解決方式:
(1)不要在主線程中做耗時的操作苦蒿,而應(yīng)放在子線程中來實現(xiàn)殴胧。如onCreate()和onResume()里盡可能少的去做創(chuàng)建操作。
(2)應(yīng)用程序應(yīng)該避免在BroadcastReceiver里做耗時的操作或計算佩迟。
(3)避免在Intent Receiver里啟動一個Activity团滥,因為它會創(chuàng)建一個新的畫面,并從當(dāng)前用戶正在運行的程序上搶奪焦點报强。
(4)service是運行在主線程的灸姊,所以在service中做耗時操作,必須要放在子線程中秉溉。
28力惯、設(shè)計模式
此處延伸:Double Check的寫法被要求寫出來。
單例模式:分為惡漢式和懶漢式
惡漢式:
public class Singleton
{
??? private static Singleton instance = new Singleton();
??? public static Singleton getInstance()
??? {
??????? return instance ;
??? }
}
懶漢式:
public class Singleton02
{
??? private static Singleton02 instance;
??? public static Singleton02 getInstance()
??? {
??????? if (instance == null)
??????? {
??????????? synchronized (Singleton02.class)
??????????? {
??????????????? if (instance == null)
???????? ???????{
??????????????????? instance = new Singleton02();
??????????????? }
??????????? }
??????? }
??????? return instance;
??? }
}
29召嘶、RxJava
30父晶、MVP,MVC弄跌,MVVM
此處延伸:手寫mvp例子甲喝,與mvc之間的區(qū)別,mvp的優(yōu)勢
MVP模式碟绑,對應(yīng)著Model--業(yè)務(wù)邏輯和實體模型,view--對應(yīng)著activity,負責(zé)View的繪制以及與用戶交互,Presenter--負責(zé)View和Model之間的交互,MVP模式是在MVC模式的基礎(chǔ)上,將Model與View徹底分離使得項目的耦合性更低鼻听,在Mvc中項目中的activity對應(yīng)著mvc中的C--Controllor,而項目中的邏輯處理都是在這個C中處理引颈,同時View與Model之間的交互,也是也就是說凯肋,mvc中所有的邏輯交互和用戶交互谊惭,都是放在Controllor中,也就是activity中侮东。View和model是可以直接通信的圈盔。而MVP模式則是分離的更加徹底,分工更加明確Model--業(yè)務(wù)邏輯和實體模型悄雅,view--負責(zé)與用戶交互驱敲,Presenter 負責(zé)完成View于Model間的交互,MVP和MVC最大的區(qū)別是MVC中是允許Model和View進行交互的宽闲,而MVP中很明顯众眨,Model與View之間的交互由Presenter完成。還有一點就是Presenter與View之間的交互是通過接口的
31容诬、手寫算法(選擇冒泡必須要會)
32娩梨、JNI
(1)安裝和下載Cygwin,下載 Android NDK
(2)在ndk項目中JNI接口的設(shè)計
(3)使用C/C++實現(xiàn)本地方法
(4)JNI生成動態(tài)鏈接庫.so文件
(5)將動態(tài)鏈接庫復(fù)制到j(luò)ava工程览徒,在java工程中調(diào)用狈定,運行java工程即可
33、RecyclerView和ListView的區(qū)別
RecyclerView可以完成ListView,GridView的效果习蓬,還可以完成瀑布流的效果纽什。同時還可以設(shè)置列表的滾動方向(垂直或者水平);
RecyclerView中view的復(fù)用不需要開發(fā)者自己寫代碼友雳,系統(tǒng)已經(jīng)幫封裝完成了稿湿。
RecyclerView可以進行局部刷新。
RecyclerView提供了API來實現(xiàn)item的動畫效果押赊。
在性能上:
如果需要頻繁的刷新數(shù)據(jù)饺藤,需要添加動畫,則RecyclerView有較大的優(yōu)勢流礁。
如果只是作為列表展示涕俗,則兩者區(qū)別并不是很大。
34神帅、Universal-ImageLoader再姑,Picasso,F(xiàn)resco找御,Glide對比
Fresco是 Facebook 推出的開源圖片緩存工具元镀,主要特點包括:兩個內(nèi)存緩存加上 Native 緩存構(gòu)成了三級緩存绍填,
優(yōu)點:
1.圖片存儲在安卓系統(tǒng)的匿名共享內(nèi)存, 而不是虛擬機的堆內(nèi)存中, 圖片的中間緩沖數(shù)據(jù)也存放在本地堆內(nèi)存, 所以, 應(yīng)用程序有更多的內(nèi)存使用, 不會因為圖片加載而導(dǎo)致oom, 同時也減少垃圾回收器頻繁調(diào)用回收 Bitmap 導(dǎo)致的界面卡頓, 性能更高。
2.漸進式加載 JPEG 圖片, 支持圖片從模糊到清晰加載栖疑。
3.圖片可以以任意的中心點顯示在 ImageView, 而不僅僅是圖片的中心讨永。
4. JPEG圖片改變大小也是在 native 進行的, 不是在虛擬機的堆內(nèi)存, 同樣減少 OOM。
5.很好的支持 GIF 圖片的顯示遇革。
缺點:
1.框架較大, 影響 Apk 體積
2.使用較繁瑣
Universal-ImageLoader:(估計由于HttpClient被Google放棄卿闹,作者就放棄維護這個框架)
優(yōu)點:
1.支持下載進度監(jiān)聽
2.可以在 View 滾動中暫停圖片加載,通過 PauseOnScrollListener 接口可以在 View 滾動中暫停圖片加載萝快。
3.默認實現(xiàn)多種內(nèi)存緩存算法 這幾個圖片緩存都可以配置緩存算法锻霎,不過 ImageLoader 默認實現(xiàn)了較多緩存算法,如 Size 最大先刪除揪漩、使用最少先刪除旋恼、最近最少使用、先進先刪除氢拥、時間最長先刪除等蚌铜。
4.支持本地緩存文件名規(guī)則定義
Picasso優(yōu)點
1.自帶統(tǒng)計監(jiān)控功能。支持圖片緩存使用的監(jiān)控嫩海,包括緩存命中率冬殃、已使用內(nèi)存大小、節(jié)省的流量等叁怪。
2.支持優(yōu)先級處理审葬。每次任務(wù)調(diào)度前會選擇優(yōu)先級高的任務(wù),比如 App 頁面中 Banner 的優(yōu)先級高于 Icon 時就很適用奕谭。
3.支持延遲到圖片尺寸計算完成加載
4.支持飛行模式涣觉、并發(fā)線程數(shù)根據(jù)網(wǎng)絡(luò)類型而變。 手機切換到飛行模式或網(wǎng)絡(luò)類型變換時會自動調(diào)整線程池最大并發(fā)數(shù)血柳,比如 wifi 最大并發(fā)為 4官册,4g 為 3,3g 為 2难捌。? 這里 Picasso 根據(jù)網(wǎng)絡(luò)類型來決定最大并發(fā)數(shù)膝宁,而不是 CPU 核數(shù)。
5.“無”本地緩存根吁。無”本地緩存员淫,不是說沒有本地緩存,而是 Picasso 自己沒有實現(xiàn)击敌,交給了 Square 的另外一個網(wǎng)絡(luò)庫 okhttp 去實現(xiàn)介返,這樣的好處是可以通過請求 Response Header 中的 Cache-Control 及 Expired 控制圖片的過期時間。
Glide優(yōu)點
1.不僅僅可以進行圖片緩存還可以緩存媒體文件。Glide 不僅是一個圖片緩存圣蝎,它支持 Gif刃宵、WebP、縮略圖徘公。甚至是 Video组去,所以更該當(dāng)做一個媒體緩存。
2.支持優(yōu)先級處理步淹。
3.與 Activity/Fragment 生命周期一致,支持 trimMemory诚撵。Glide 對每個 context 都保持一個 RequestManager缭裆,通過 FragmentTransaction 保持與 Activity/Fragment 生命周期一致,并且有對應(yīng)的 trimMemory 接口實現(xiàn)可供調(diào)用寿烟。
4.支持 okhttp澈驼、Volley。Glide 默認通過 UrlConnection 獲取數(shù)據(jù)筛武,可以配合 okhttp 或是 Volley 使用缝其。實際 ImageLoader、Picasso 也都支持 okhttp徘六、Volley内边。
5.內(nèi)存友好。Glide 的內(nèi)存緩存有個 active 的設(shè)計待锈,從內(nèi)存緩存中取數(shù)據(jù)時漠其,不像一般的實現(xiàn)用 get,而是用 remove竿音,再將這個緩存數(shù)據(jù)放到一個 value 為軟引用的 activeResources map 中和屎,并計數(shù)引用數(shù),在圖片加載完成后進行判斷春瞬,如果引用計數(shù)為空則回收掉柴信。內(nèi)存緩存更小圖片,Glide 以 url宽气、view_width随常、view_height、屏幕的分辨率等做為聯(lián)合 key抹竹,將處理后的圖片緩存在內(nèi)存緩存中线罕,而不是原始圖片以節(jié)省大小與 Activity/Fragment 生命周期一致,支持 trimMemory窃判。圖片默認使用默認 RGB_565 而不是 ARGB_888钞楼,雖然清晰度差些,但圖片更小袄琳,也可配置到 ARGB_888询件。
6.Glide可以通過 signature 或不使用本地緩存支持 url 過期
42燃乍、Xutils, OKhttp, Volley, Retrofit對比
Xutils這個框架非常全面,可以進行網(wǎng)絡(luò)請求宛琅,可以進行圖片加載處理刻蟹,可以數(shù)據(jù)儲存,還可以對view進行注解嘿辟,使用這個框架非常方便舆瘪,但是缺點也是非常明顯的,使用這個項目红伦,會導(dǎo)致項目對這個框架依賴非常的嚴重英古,一旦這個框架出現(xiàn)問題,那么對項目來說影響非常大的昙读。召调、
OKhttp:Android開發(fā)中是可以直接使用現(xiàn)成的api進行網(wǎng)絡(luò)請求的。就是使用HttpClient,HttpUrlConnection進行操作蛮浑。okhttp針對Java和Android程序唠叛,封裝的一個高性能的http請求庫,支持同步沮稚,異步艺沼,而且okhttp又封裝了線程池,封裝了數(shù)據(jù)轉(zhuǎn)換蕴掏,封裝了參數(shù)的使用澳厢,錯誤處理等。API使用起來更加的方便囚似。但是我們在項目中使用的時候仍然需要自己在做一層封裝剩拢,這樣才能使用的更加的順手。
Volley:Volley是Google官方出的一套小而巧的異步請求庫饶唤,該框架封裝的擴展性很強徐伐,支持HttpClient、HttpUrlConnection募狂, 甚至支持OkHttp办素,而且Volley里面也封裝了ImageLoader,所以如果你愿意你甚至不需要使用圖片加載框架祸穷,不過這塊功能沒有一些專門的圖片加載框架強大性穿,對于簡單的需求可以使用,稍復(fù)雜點的需求還是需要用到專門的圖片加載框架雷滚。Volley也有缺陷需曾,比如不支持post大數(shù)據(jù),所以不適合上傳文件。不過Volley設(shè)計的初衷本身也就是為頻繁的呆万、數(shù)據(jù)量小的網(wǎng)絡(luò)請求而生商源。
Retrofit:Retrofit是Square公司出品的默認基于OkHttp封裝的一套RESTful網(wǎng)絡(luò)請求框架,RESTful是目前流行的一套api設(shè)計的風(fēng)格谋减, 并不是標準牡彻。Retrofit的封裝可以說是很強大,里面涉及到一堆的設(shè)計模式,可以通過注解直接配置請求出爹,可以使用不同的http客戶端庄吼,雖然默認是用http ,可以使用不同Json Converter 來序列化數(shù)據(jù)严就,同時提供對RxJava的支持霸褒,使用Retrofit + OkHttp + RxJava + Dagger2 可以說是目前比較潮的一套框架,但是需要有比較高的門檻盈蛮。
Volley VS OkHttp
Volley的優(yōu)勢在于封裝的更好,而使用OkHttp你需要有足夠的能力再進行一次封裝技矮。而OkHttp的優(yōu)勢在于性能更高抖誉,因為 OkHttp基于NIO和Okio ,所以性能上要比 Volley更快衰倦。IO 和 NIO這兩個都是Java中的概念袒炉,如果我從硬盤讀取數(shù)據(jù),第一種方式就是程序一直等樊零,數(shù)據(jù)讀完后才能繼續(xù)操作這種是最簡單的也叫阻塞式IO,還有一種是你讀你的,程序接著往下執(zhí)行我磁,等數(shù)據(jù)處理完你再來通知我,然后再處理回調(diào)驻襟。而第二種就是 NIO 的方式夺艰,非阻塞式, 所以NIO當(dāng)然要比IO的性能要好了,而 Okio是 Square 公司基于IO和NIO基礎(chǔ)上做的一個更簡單沉衣、高效處理數(shù)據(jù)流的一個庫郁副。理論上如果Volley和OkHttp對比的話,更傾向于使用 Volley豌习,因為Volley內(nèi)部同樣支持使用OkHttp,這點OkHttp的性能優(yōu)勢就沒了存谎,? 而且 Volley 本身封裝的也更易用,擴展性更好些肥隆。
OkHttp VS Retrofit
毫無疑問既荚,Retrofit默認是基于 OkHttp 而做的封裝,這點來說沒有可比性栋艳,肯定首選 Retrofit恰聘。
Volley VS Retrofit
這兩個庫都做了不錯的封裝,但Retrofit解耦的更徹底,尤其Retrofit2.0出來,Jake對之前1.0設(shè)計不合理的地方做了大量重構(gòu)憨琳, 職責(zé)更細分诫钓,而且Retrofit默認使用OkHttp,性能上也要比Volley占優(yōu)勢,再有如果你的項目如果采用了RxJava 篙螟,那更該使用? Retrofit 菌湃。所以這兩個庫相比,Retrofit更有優(yōu)勢遍略,在能掌握兩個框架的前提下該優(yōu)先使用 Retrofit惧所。但是Retrofit門檻要比Volley稍高些,要理解他的原理绪杏,各種用法下愈,想徹底搞明白還是需要花些功夫的,如果你對它一知半解蕾久,那還是建議在商業(yè)項目使用Volley吧势似。
Java
1、線程中sleep和wait的區(qū)別
(1)這兩個方法來自不同的類僧著,sleep是來自Thread履因,wait是來自O(shè)bject;
(2)sleep方法沒有釋放鎖盹愚,而wait方法釋放了鎖栅迄。
(3)wait,notify,notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用皆怕。
2毅舆、Thread中的start()和run()方法有什么區(qū)別
start()方法是用來啟動新創(chuàng)建的線程,而start()內(nèi)部調(diào)用了run()方法愈腾,這和直接調(diào)用run()方法是不一樣的憋活,如果直接調(diào)用run()方法,
則和普通的方法沒有什么區(qū)別虱黄。
3余掖、關(guān)鍵字final和static是怎么使用的。
final:
1礁鲁、final變量即為常量盐欺,只能賦值一次。
2仅醇、final方法不能被子類重寫冗美。
3、final類不能被繼承析二。
static:
1粉洼、static變量:對于靜態(tài)變量在內(nèi)存中只有一個拷貝(節(jié)省內(nèi)存)节预,JVM只為靜態(tài)分配一次內(nèi)存,
在加載類的過程中完成靜態(tài)變量的內(nèi)存分配属韧,可用類名直接訪問(方便)安拟,當(dāng)然也可以通過對象來訪問(但是這是不推薦的)。
2宵喂、static代碼塊
static代碼塊是類加載時糠赦,初始化自動執(zhí)行的。
3锅棕、static方法
static方法可以直接通過類名調(diào)用拙泽,任何的實例也都可以調(diào)用,因此static方法中不能用this和super關(guān)鍵字裸燎,
不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法)顾瞻,只能訪問所屬類的靜態(tài)成員變量和成員方法。
4德绿、String,StringBuffer,StringBuilder區(qū)別
1荷荤、三者在執(zhí)行速度上:StringBuilder > StringBuffer > String (由于String是常量,不可改變移稳,拼接時會重新創(chuàng)建新的對象)蕴纳。
2、StringBuffer是線程安全的秒裕,StringBuilder是線程不安全的。(由于StringBuffer有緩沖區(qū))
5钞啸、Java中重載和重寫的區(qū)別:
1几蜻、重載:一個類中可以有多個相同方法名的,但是參數(shù)類型和個數(shù)都不一樣体斩。這是重載梭稚。
2、重寫:子類繼承父類絮吵,則子類可以通過實現(xiàn)父類中的方法弧烤,從而新的方法把父類舊的方法覆蓋。
6蹬敲、Http https區(qū)別
此處延伸:https的實現(xiàn)原理
1暇昂、https協(xié)議需要到ca申請證書,一般免費證書較少伴嗡,因而需要一定費用急波。
2、http是超文本傳輸協(xié)議瘪校,信息是明文傳輸澄暮,https則是具有安全性的ssl加密傳輸協(xié)議名段。
3、http和https使用的是完全不同的連接方式泣懊,用的端口也不一樣伸辟,前者是80,后者是443馍刮。
4信夫、http的連接很簡單,是無狀態(tài)的渠退;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸忙迁、身份認證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全碎乃。
https實現(xiàn)原理:
(1)客戶使用https的URL訪問Web服務(wù)器姊扔,要求與Web服務(wù)器建立SSL連接。
(2)Web服務(wù)器收到客戶端請求后梅誓,會將網(wǎng)站的證書信息(證書中包含公鑰)傳送一份給客戶端恰梢。
(3)客戶端的瀏覽器與Web服務(wù)器開始協(xié)商SSL連接的安全等級,也就是信息加密的等級梗掰。
(4)客戶端的瀏覽器根據(jù)雙方同意的安全等級嵌言,建立會話密鑰,然后利用網(wǎng)站的公鑰將會話密鑰加密及穗,并傳送給網(wǎng)站摧茴。
(5)Web服務(wù)器利用自己的私鑰解密出會話密鑰。
(6)Web服務(wù)器利用會話密鑰加密與客戶端之間的通信埂陆。
7苛白、Http位于TCP/IP模型中的第幾層?為什么說Http是可靠的數(shù)據(jù)傳輸協(xié)議焚虱?
tcp/ip的五層模型:
從下到上:物理層->數(shù)據(jù)鏈路層->網(wǎng)絡(luò)層->傳輸層->應(yīng)用層
其中tcp/ip位于模型中的網(wǎng)絡(luò)層购裙,處于同一層的還有ICMP(網(wǎng)絡(luò)控制信息協(xié)議)。http位于模型中的應(yīng)用層
由于tcp/ip是面向連接的可靠協(xié)議鹃栽,而http是在傳輸層基于tcp/ip協(xié)議的躏率,所以說http是可靠的數(shù)據(jù)傳輸協(xié)議。
8民鼓、HTTP鏈接的特點
HTTP連接最顯著的特點是客戶端發(fā)送的每次請求都需要服務(wù)器回送響應(yīng)薇芝,在請求結(jié)束后,會主動釋放連接丰嘉。
從建立連接到關(guān)閉連接的過程稱為“一次連接”恩掷。
9、TCP和UDP的區(qū)別
tcp是面向連接的供嚎,由于tcp連接需要三次握手黄娘,所以能夠最低限度的降低風(fēng)險峭状,保證連接的可靠性。
udp不是面向連接的逼争,udp建立連接前不需要與對象建立連接优床,無論是發(fā)送還是接收,都沒有發(fā)送確認信號誓焦。所以說udp是不可靠的胆敞。
由于udp不需要進行確認連接,使得UDP的開銷更小杂伟,傳輸速率更高移层,所以實時行更好。
10赫粥、Socket建立網(wǎng)絡(luò)連接的步驟
建立Socket連接至少需要一對套接字观话,其中一個運行與客戶端--ClientSocket,一個運行于服務(wù)端--ServiceSocket
1越平、服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字频蛔,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài)秦叛,等待客戶端的連接請求晦溪。
2、客戶端請求:指客戶端的套接字提出連接請求挣跋,要連接的目標是服務(wù)器端的套接字三圆。注意:客戶端的套接字必須描述他要連接的服務(wù)器的套接字,
指出服務(wù)器套接字的地址和端口號避咆,然后就像服務(wù)器端套接字提出連接請求舟肉。
3、連接確認:當(dāng)服務(wù)器端套接字監(jiān)聽到客戶端套接字的連接請求時牌借,就響應(yīng)客戶端套接字的請求度气,建立一個新的線程割按,把服務(wù)器端套接字的描述
發(fā)給客戶端膨报,一旦客戶端確認了此描述,雙方就正式建立連接适荣。而服務(wù)端套接字則繼續(xù)處于監(jiān)聽狀態(tài)现柠,繼續(xù)接收其他客戶端套接字的連接請求。