onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()2、Service生命周期?service 啟動(dòng)方式有兩種,一種是通..."/>
您好,登錄后才能下訂單哦!
1、Activity生命周期?
onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()
2、Service生命周期?
service 啟動(dòng)方式有兩種,一種是通過(guò)startService()方式進(jìn)行啟動(dòng),另一種是通過(guò)bindService()方式進(jìn)行啟動(dòng)。不同的啟動(dòng)方式他們的生命周期是不一樣.
通過(guò)startService()這種方式啟動(dòng)的service,生命周期是這樣:調(diào)用startService() --> onCreate()--> onStartConmon()--> onDestroy()。這種方式啟動(dòng)的話,需要注意一下幾個(gè)問(wèn)題,第一:當(dāng)我們通過(guò)startService被調(diào)用以后,多次在調(diào)用startService(),onCreate()方法也只會(huì)被調(diào)用一次,而onStartConmon()會(huì)被多次調(diào)用當(dāng)我們調(diào)用stopService()的時(shí)候,onDestroy()就會(huì)被調(diào)用,從而銷毀服務(wù)。第二:當(dāng)我們通過(guò)startService啟動(dòng)時(shí)候,通過(guò)intent傳值,在onStartConmon()方法中獲取值的時(shí)候,一定要先判斷intent是否為null。
通過(guò)bindService()方式進(jìn)行綁定,這種方式綁定service,生命周期走法:bindService-->onCreate()-->onBind()-->unBind()-->onDestroy() bingservice 這種方式進(jìn)行啟動(dòng)service好處是更加便利activity中操作service,比如加入service中有幾個(gè)方法,a,b ,如果要在activity中調(diào)用,在需要在activity獲取ServiceConnection對(duì)象,通過(guò)ServiceConnection來(lái)獲取service中內(nèi)部類的類對(duì)象,然后通過(guò)這個(gè)類對(duì)象就可以調(diào)用類中的方法,當(dāng)然這個(gè)類需要繼承Binder對(duì)象
3、Activity的啟動(dòng)過(guò)程(不要回答生命周期)
app啟動(dòng)的過(guò)程有兩種情況,第一種是從桌面launcher上點(diǎn)擊相應(yīng)的應(yīng)用圖標(biāo),第二種是在activity中通過(guò)調(diào)用startActivity來(lái)啟動(dòng)一個(gè)新的activity。
我們創(chuàng)建一個(gè)新的項(xiàng)目,默認(rèn)的根activity都是MainActivity,而所有的activity都是保存在堆棧中的,我們啟動(dòng)一個(gè)新的activity就會(huì)放在上一個(gè)activity上面,而我們從桌面點(diǎn)擊應(yīng)用圖標(biāo)的時(shí)候,由于launcher本身也是一個(gè)應(yīng)用,當(dāng)我們點(diǎn)擊圖標(biāo)的時(shí)候,系統(tǒng)就會(huì)調(diào)用startActivitySately(),一般情況下,我們所啟動(dòng)的activity的相關(guān)信息都會(huì)保存在intent中,比如action,category等等。我們?cè)诎惭b這個(gè)應(yīng)用的時(shí)候,系統(tǒng)也會(huì)啟動(dòng)一個(gè)PackaManagerService的管理服務(wù),這個(gè)管理服務(wù)會(huì)對(duì)AndroidManifest.xml文件進(jìn)行解析,從而得到應(yīng)用程序中的相關(guān)信息,比如service,activity,Broadcast等等,然后獲得相關(guān)組件的信息。當(dāng)我們點(diǎn)擊應(yīng)用圖標(biāo)的時(shí)候,就會(huì)調(diào)用startActivitySately()方法,而這個(gè)方法內(nèi)部則是調(diào)用startActivty(),而startActivity()方法最終還是會(huì)調(diào)用startActivityForResult()這個(gè)方法。而在startActivityForResult()這個(gè)方法。因?yàn)閟tartActivityForResult()方法是有返回結(jié)果的,所以系統(tǒng)就直接給一個(gè)-1,就表示不需要結(jié)果返回了。而startActivityForResult()這個(gè)方法實(shí)際是通過(guò)Instrumentation類中的execStartActivity()方法來(lái)啟動(dòng)activity,Instrumentation這個(gè)類主要作用就是監(jiān)控程序和系統(tǒng)之間的交互。而在這個(gè)execStartActivity()方法中會(huì)獲取ActivityManagerService的代理對(duì)象,通過(guò)這個(gè)代理對(duì)象進(jìn)行啟動(dòng)activity。啟動(dòng)會(huì)就會(huì)調(diào)用一個(gè)checkStartActivityResult()方法,如果說(shuō)沒有在配置清單中配置有這個(gè)組件,就會(huì)在這個(gè)方法中拋出異常了。當(dāng)然最后是調(diào)用的是Application.scheduleLaunchActivity()進(jìn)行啟動(dòng)activity,而這個(gè)方法中通過(guò)獲取得到一個(gè)ActivityClientRecord對(duì)象,而這個(gè)ActivityClientRecord通過(guò)handler來(lái)進(jìn)行消息的發(fā)送,系統(tǒng)內(nèi)部會(huì)將每一個(gè)activity組件使用ActivityClientRecord對(duì)象來(lái)進(jìn)行描述,而ActivityClientRecord對(duì)象中保存有一個(gè)LoaderApk對(duì)象,通過(guò)這個(gè)對(duì)象調(diào)用handleLaunchActivity來(lái)啟動(dòng)activity組件,而頁(yè)面的生命周期方法也就是在這個(gè)方法中進(jìn)行調(diào)用。
4、Broadcast注冊(cè)方式與區(qū)別
此處延伸:什么情況下用動(dòng)態(tài)注冊(cè)
Broadcast廣播,注冊(cè)方式主要有兩種.
第一種是靜態(tài)注冊(cè),也可成為常駐型廣播,這種廣播需要在Androidmanifest.xml中進(jìn)行注冊(cè),這中方式注冊(cè)的廣播,不受頁(yè)面生命周期的影響,即使退出了頁(yè)面,也可以收到廣播這種廣播一般用于想開機(jī)自啟動(dòng)啊等等,由于這種注冊(cè)的方式的廣播是常駐型廣播,所以會(huì)占用CPU的資源。
第二種是動(dòng)態(tài)注冊(cè),而動(dòng)態(tài)注冊(cè)的話,是在代碼中注冊(cè)的,這種注冊(cè)方式也叫非常駐型廣播,收到生命周期的影響,退出頁(yè)面后,就不會(huì)收到廣播,我們通常運(yùn)用在更新UI方面。這種注冊(cè)方式優(yōu)先級(jí)較高。最后需要解綁,否會(huì)會(huì)內(nèi)存泄露
廣播是分為有序廣播和無(wú)序廣播。
5、HttpClient與HttpUrlConnection的區(qū)別
此處延伸:Volley里用的哪種請(qǐng)求方式(2.3前HttpClient,2.3后HttpUrlConnection)
首先HttpClient和HttpUrlConnection 這兩種方式都支持Https協(xié)議,都是以流的形式進(jìn)行上傳或者下載數(shù)據(jù),也可以說(shuō)是以流的形式進(jìn)行數(shù)據(jù)的傳輸,還有ipv6,以及連接池等功能。HttpClient這個(gè)擁有非常多的API,所以如果想要進(jìn)行擴(kuò)展的話,并且不破壞它的兼容性的話,很難進(jìn)行擴(kuò)展,也就是這個(gè)原因,Google在Android6.0的時(shí)候,直接就棄用了這個(gè)HttpClient.
而HttpUrlConnection相對(duì)來(lái)說(shuō)就是比較輕量級(jí)了,API比較少,容易擴(kuò)展,并且能夠滿足Android大部分的數(shù)據(jù)傳輸。比較經(jīng)典的一個(gè)框架volley,在2.3版本以前都是使用HttpClient,在2.3以后就使用了HttpUrlConnection。
6、java虛擬機(jī)和Dalvik虛擬機(jī)的區(qū)別
Java虛擬機(jī):
1、java虛擬機(jī)基于棧。 基于棧的機(jī)器必須使用指令來(lái)載入和操作棧上數(shù)據(jù),所需指令更多更多。
2、java虛擬機(jī)運(yùn)行的是java字節(jié)碼。(java類會(huì)被編譯成一個(gè)或多個(gè)字節(jié)碼.class文件)
Dalvik虛擬機(jī):
1、dalvik虛擬機(jī)是基于寄存器的
2、Dalvik運(yùn)行的是自定義的.dex字節(jié)碼格式。(java類被編譯成.class文件后,會(huì)通過(guò)一個(gè)dx工具將所有的.class文件轉(zhuǎn)換成一個(gè).dex文件,然后dalvik虛擬機(jī)會(huì)從其中讀取指令和數(shù)據(jù)
3、常量池已被修改為只使用32位的索引,以 簡(jiǎn)化解釋器。
4、一個(gè)應(yīng)用,一個(gè)虛擬機(jī)實(shí)例,一個(gè)進(jìn)程(所有android應(yīng)用的線程都是對(duì)應(yīng)一個(gè)linux線程,都運(yùn)行在自己的沙盒中,不同的應(yīng)用在不同的進(jìn)程中運(yùn)行。每個(gè)android dalvik應(yīng)用程序都被賦予了一個(gè)獨(dú)立的linux PID(app_*))
7、進(jìn)程?;睿ú凰肋M(jìn)程)
此處延伸:進(jìn)程的優(yōu)先級(jí)是什么
當(dāng)前業(yè)界的Android進(jìn)程保活手段主要分為** 黑、白、灰 **三種,其大致的實(shí)現(xiàn)思路如下:
黑色?;睿翰煌腶pp進(jìn)程,用廣播相互喚醒(包括利用系統(tǒng)提供的廣播進(jìn)行喚醒)
白色?;睿?jiǎn)?dòng)前臺(tái)Service
灰色?;睿豪孟到y(tǒng)的漏洞啟動(dòng)前臺(tái)Service
黑色?;?/p>
所謂黑色?;?,就是利用不同的app進(jìn)程使用廣播來(lái)進(jìn)行相互喚醒。舉個(gè)3個(gè)比較常見的場(chǎng)景:
場(chǎng)景1:開機(jī),網(wǎng)絡(luò)切換、拍照、拍視頻時(shí)候,利用系統(tǒng)產(chǎn)生的廣播喚醒a(bǔ)pp
場(chǎng)景2:接入第三方SDK也會(huì)喚醒相應(yīng)的app進(jìn)程,如微信sdk會(huì)喚醒微信,支付寶sdk會(huì)喚醒支付寶。由此發(fā)散開去,就會(huì)直接觸發(fā)了下面的 場(chǎng)景3
場(chǎng)景3:假如你手機(jī)里裝了支付寶、淘寶、天貓、UC等阿里系的app,那么你打開任意一個(gè)阿里系的app后,有可能就順便把其他阿里系的app給喚醒了。(只是拿阿里打個(gè)比方,其實(shí)BAT系都差不多)
白色?;?/p>
白色?;钍侄畏浅:?jiǎn)單,就是調(diào)用系統(tǒng)api啟動(dòng)一個(gè)前臺(tái)的Service進(jìn)程,這樣會(huì)在系統(tǒng)的通知欄生成一個(gè)Notification,用來(lái)讓用戶知道有這樣一個(gè)app在運(yùn)行著,哪怕當(dāng)前的app退到了后臺(tái)。如下方的LBE和QQ音樂(lè)這樣:
灰色保活
灰色?;?,這種?;钍侄问菓?yīng)用范圍最廣泛。它是利用系統(tǒng)的漏洞來(lái)啟動(dòng)一個(gè)前臺(tái)的Service進(jìn)程,與普通的啟動(dòng)方式區(qū)別在于,它不會(huì)在系統(tǒng)通知欄處出現(xiàn)一個(gè)Notification,看起來(lái)就如同運(yùn)行著一個(gè)后臺(tái)Service進(jìn)程一樣。這樣做帶來(lái)的好處就是,用戶無(wú)法察覺到你運(yùn)行著一個(gè)前臺(tái)進(jìn)程(因?yàn)榭床坏絅otification),但你的進(jìn)程優(yōu)先級(jí)又是高于普通后臺(tái)進(jìn)程的。那么如何利用系統(tǒng)的漏洞呢,大致的實(shí)現(xiàn)思路和代碼如下:
思路一:API < 18,啟動(dòng)前臺(tái)Service時(shí)直接傳入new Notification();
思路二:API >= 18,同時(shí)啟動(dòng)兩個(gè)id相同的前臺(tái)Service,然后再將后啟動(dòng)的Service做stop處理
熟悉Android系統(tǒng)的童鞋都知道,系統(tǒng)出于體驗(yàn)和性能上的考慮,app在退到后臺(tái)時(shí)系統(tǒng)并不會(huì)真正的kill掉這個(gè)進(jìn)程,而是將其緩存起來(lái)。打開的應(yīng)用越多,后臺(tái)緩存的進(jìn)程也越多。在系統(tǒng)內(nèi)存不足的情況下,系統(tǒng)開始依據(jù)自身的一套進(jìn)程回收機(jī)制來(lái)判斷要kill掉哪些進(jìn)程,以騰出內(nèi)存來(lái)供給需要的app。這套殺進(jìn)程回收內(nèi)存的機(jī)制就叫 Low Memory Killer ,它是基于Linux內(nèi)核的 OOM Killer(Out-Of-Memory killer)機(jī)制誕生。
進(jìn)程的重要性,劃分5級(jí):
前臺(tái)進(jìn)程 (Foreground process)
可見進(jìn)程 (Visible process)
服務(wù)進(jìn)程 (Service process)
后臺(tái)進(jìn)程 (Background process)
空進(jìn)程 (Empty process)
了解完 Low Memory Killer,再科普一下oom_adj。什么是oom_adj?它是linux內(nèi)核分配給每個(gè)系統(tǒng)進(jìn)程的一個(gè)值,代表進(jìn)程的優(yōu)先級(jí),進(jìn)程回收機(jī)制就是根據(jù)這個(gè)優(yōu)先級(jí)來(lái)決定是否進(jìn)行回收。對(duì)于oom_adj的作用,你只需要記住以下幾點(diǎn)即可:
進(jìn)程的oom_adj越大,表示此進(jìn)程優(yōu)先級(jí)越低,越容易被殺回收;越小,表示進(jìn)程優(yōu)先級(jí)越高,越不容易被殺回收
普通app進(jìn)程的oom_adj>=0,系統(tǒng)進(jìn)程的oom_adj才可能<0
有些手機(jī)廠商把這些知名的app放入了自己的白名單中,保證了進(jìn)程不死來(lái)提高用戶體驗(yàn)(如微信、QQ、陌陌都在小米的白名單中)。如果從白名單中移除,他們終究還是和普通app一樣躲避不了被殺的命運(yùn),為了盡量避免被殺,還是老老實(shí)實(shí)去做好優(yōu)化工作吧。
所以,進(jìn)程保活的根本方案終究還是回到了性能優(yōu)化上,進(jìn)程永生不死終究是個(gè)徹頭徹尾的偽命題!
8、講解一下Context
Context是一個(gè)抽象基類。在翻譯為上下文,也可以理解為環(huán)境,是提供一些程序的運(yùn)行環(huán)境基礎(chǔ)信息。Context下有兩個(gè)子類,ContextWrapper是上下文功能的封裝類,而ContextImpl則是上下文功能的實(shí)現(xiàn)類。而ContextWrapper又有三個(gè)直接的子類, ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一個(gè)帶主題的封裝類,而它有一個(gè)直接子類就是Activity,所以Activity和Service以及Application的Context是不一樣的,只有Activity需要主題,Service不需要主題。Context一共有三種類型,分別是Application、Activity和Service。這三個(gè)類雖然分別各種承擔(dān)著不同的作用,但它們都屬于Context的一種,而它們具體Context的功能則是由ContextImpl類去實(shí)現(xiàn)的,因此在絕大多數(shù)場(chǎng)景下,Activity、Service和Application這三種類型的Context都是可以通用的。不過(guò)有幾種場(chǎng)景比較特殊,比如啟動(dòng)Activity,還有彈出Dialog。出于安全原因的考慮,Android是不允許Activity或Dialog憑空出現(xiàn)的,一個(gè)Activity的啟動(dòng)必須要建立在另一個(gè)Activity的基礎(chǔ)之上,也就是以此形成的返回棧。而Dialog則必須在一個(gè)Activity上面彈出(除非是System Alert類型的Dialog),因此在這種場(chǎng)景下,我們只能使用Activity類型的Context,否則將會(huì)出錯(cuò)。
getApplicationContext()和getApplication()方法得到的對(duì)象都是同一個(gè)application對(duì)象,只是對(duì)象的類型不一樣。
Context數(shù)量 = Activity數(shù)量 + Service數(shù)量 + 1 (1為Application)
9、理解Activity,View,Window三者關(guān)系
這個(gè)問(wèn)題真的很不好回答。所以這里先來(lái)個(gè)算是比較恰當(dāng)?shù)谋扔鱽?lái)形容下它們的關(guān)系吧。Activity像一個(gè)工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖)LayoutInflater像剪刀,Xml配置像窗花圖紙。
1:Activity構(gòu)造的時(shí)候會(huì)初始化一個(gè)Window,準(zhǔn)確的說(shuō)是PhoneWindow。
2:這個(gè)PhoneWindow有一個(gè)“ViewRoot”,這個(gè)“ViewRoot”是一個(gè)View或者說(shuō)ViewGroup,是最初始的根視圖。
3:“ViewRoot”通過(guò)addView方法來(lái)一個(gè)個(gè)的添加View。比如TextView,Button等
4:這些View的事件監(jiān)聽,是由WindowManagerService來(lái)接受消息,并且回調(diào)Activity函數(shù)。比如onClickListener,onKeyDown等。
10、四種LaunchMode及其使用場(chǎng)景
此處延伸:棧(First In Last Out)與隊(duì)列(First In First Out)的區(qū)別
棧與隊(duì)列的區(qū)別:
隊(duì)列先進(jìn)先出,棧先進(jìn)后出
2. 對(duì)插入和刪除操作的"限定"。 棧是限定只能在表的一端進(jìn)行插入和刪除操作的線性表。 隊(duì)列是限定只能在表的一端進(jìn)行插入和在另一端進(jìn)行刪除操作的線性表。
3. 遍歷數(shù)據(jù)速度不同
standard 模式
這是默認(rèn)模式,每次激活A(yù)ctivity時(shí)都會(huì)創(chuàng)建Activity實(shí)例,并放入任務(wù)棧中。使用場(chǎng)景:大多數(shù)Activity。
singleTop 模式
如果在任務(wù)的棧頂正好存在該Activity的實(shí)例,就重用該實(shí)例( 會(huì)調(diào)用實(shí)例的 onNewIntent() ),否則就會(huì)創(chuàng)建新的實(shí)例并放入棧頂,即使棧中已經(jīng)存在該Activity的實(shí)例,只要不在棧頂,都會(huì)創(chuàng)建新的實(shí)例。使用場(chǎng)景如新聞?lì)惢蛘唛喿x類App的內(nèi)容頁(yè)面。
singleTask 模式
如果在棧中已經(jīng)有該Activity的實(shí)例,就重用該實(shí)例(會(huì)調(diào)用實(shí)例的 onNewIntent() )。重用時(shí),會(huì)讓該實(shí)例回到棧頂,因此在它上面的實(shí)例將會(huì)被移出棧。如果棧中不存在該實(shí)例,將會(huì)創(chuàng)建新的實(shí)例放入棧中。使用場(chǎng)景如瀏覽器的主界面。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器,只會(huì)啟動(dòng)主界面一次,其余情況都會(huì)走onNewIntent,并且會(huì)清空主界面上面的其他頁(yè)面。
singleInstance 模式
在一個(gè)新棧中創(chuàng)建該Activity的實(shí)例,并讓多個(gè)應(yīng)用共享該棧中的該Activity實(shí)例。一旦該模式的Activity實(shí)例已經(jīng)存在于某個(gè)棧中,任何應(yīng)用再激活該Activity時(shí)都會(huì)重用該棧中的實(shí)例( 會(huì)調(diào)用實(shí)例的 onNewIntent() )。其效果相當(dāng)于多個(gè)應(yīng)用共享一個(gè)應(yīng)用,不管誰(shuí)激活該 Activity 都會(huì)進(jìn)入同一個(gè)應(yīng)用中。使用場(chǎng)景如鬧鈴提醒,將鬧鈴提醒與鬧鈴設(shè)置分離。singleInstance不要用于中間頁(yè)面,如果用于中間頁(yè)面,跳轉(zhuǎn)會(huì)有問(wèn)題,比如:A -> B (singleInstance) -> C,完全退出后,在此啟動(dòng),首先打開的是B。
11、View的繪制流程
自定義控件:
1、組合控件。這種自定義控件不需要我們自己繪制,而是使用原生控件組合成的新控件。如標(biāo)題欄。
2、繼承原有的控件。這種自定義控件在原生控件提供的方法外,可以自己添加一些方法。如制作圓角,圓形圖片。
3、完全自定義控件:這個(gè)View上所展現(xiàn)的內(nèi)容全部都是我們自己繪制出來(lái)的。比如說(shuō)制作水波紋進(jìn)度條。
View的繪制流程:OnMeasure()——>OnLayout()——>OnDraw()
第一步:OnMeasure():測(cè)量視圖大小。從頂層父View到子View遞歸調(diào)用measure方法,measure方法又回調(diào)OnMeasure。
第二步:OnLayout():確定View位置,進(jìn)行頁(yè)面布局。從頂層父View向子View的遞歸調(diào)用view.layout方法的過(guò)程,即父View根據(jù)上一步measure子View所得到的布局大小和布局參數(shù),將子View放在合適的位置上。
第三步:OnDraw():繪制視圖。ViewRoot創(chuàng)建一個(gè)Canvas對(duì)象,然后調(diào)用OnDraw()。六個(gè)步驟:①、繪制視圖的背景;②、保存畫布的圖層(Layer);③、繪制View的內(nèi)容;④、繪制View子視圖,如果沒有就不用;
⑤、還原圖層(Layer);⑥、繪制滾動(dòng)條。
12、View,ViewGroup事件分發(fā)
[圖片上傳中...(image-862be6-1542630926849-0)]
1. Touch事件分發(fā)中只有兩個(gè)主角:ViewGroup和View。ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三個(gè)相關(guān)事件。View包含dispatchTouchEvent、onTouchEvent兩個(gè)相關(guān)事件。其中ViewGroup又繼承于View。
2.ViewGroup和View組成了一個(gè)樹狀結(jié)構(gòu),根節(jié)點(diǎn)為Activity內(nèi)部包含的一個(gè)ViwGroup。
3.觸摸事件由Action_Down、Action_Move、Aciton_UP組成,其中一次完整的觸摸事件中,Down和Up都只有一個(gè),Move有若干個(gè),可以為0個(gè)。
4.當(dāng)Acitivty接收到Touch事件時(shí),將遍歷子View進(jìn)行Down事件的分發(fā)。ViewGroup的遍歷可以看成是遞歸的。分發(fā)的目的是為了找到真正要處理本次完整觸摸事件的View,這個(gè)View會(huì)在onTouchuEvent結(jié)果返回true。
5.當(dāng)某個(gè)子View返回true時(shí),會(huì)中止Down事件的分發(fā),同時(shí)在ViewGroup中記錄該子View。接下去的Move和Up事件將由該子View直接進(jìn)行處理。由于子View是保存在ViewGroup中的,多層ViewGroup的節(jié)點(diǎn)結(jié)構(gòu)時(shí),上級(jí)ViewGroup保存的會(huì)是真實(shí)處理事件的View所在的ViewGroup對(duì)象:如ViewGroup0-ViewGroup1-TextView的結(jié)構(gòu)中,TextView返回了true,它將被保存在ViewGroup1中,而ViewGroup1也會(huì)返回true,被保存在ViewGroup0中。當(dāng)Move和UP事件來(lái)時(shí),會(huì)先從ViewGroup0傳遞至ViewGroup1,再由ViewGroup1傳遞至TextView。
6.當(dāng)ViewGroup中所有子View都不捕獲Down事件時(shí),將觸發(fā)ViewGroup自身的onTouch事件。觸發(fā)的方式是調(diào)用super.dispatchTouchEvent函數(shù),即父類View的dispatchTouchEvent方法。在所有子View都不處理的情況下,觸發(fā)Acitivity的onTouchEvent方法。
7.onInterceptTouchEvent有兩個(gè)作用:1.攔截Down事件的分發(fā)。2.中止Up和Move事件向目標(biāo)View傳遞,使得目標(biāo)View所在的ViewGroup捕獲Up和Move事件。
13、保存Activity狀態(tài)
onSaveInstanceState(Bundle)會(huì)在activity轉(zhuǎn)入后臺(tái)狀態(tài)之前被調(diào)用,也就是onStop()方法之前,onPause方法之后被調(diào)用;
14、Android中的幾種動(dòng)畫
幀動(dòng)畫:指通過(guò)指定每一幀的圖片和播放時(shí)間,有序的進(jìn)行播放而形成動(dòng)畫效果,比如想聽的律動(dòng)條。
補(bǔ)間動(dòng)畫:指通過(guò)指定View的初始狀態(tài)、變化時(shí)間、方式,通過(guò)一系列的算法去進(jìn)行圖形變換,從而形成動(dòng)畫效果,主要有Alpha、Scale、Translate、Rotate四種效果。注意:只是在視圖層實(shí)現(xiàn)了動(dòng)畫效果,并沒有真正改變View的屬性,比如滑動(dòng)列表,改變標(biāo)題欄的透明度。
屬性動(dòng)畫:在Android3.0的時(shí)候才支持,通過(guò)不斷的改變View的屬性,不斷的重繪而形成動(dòng)畫效果。相比于視圖動(dòng)畫,View的屬性是真正改變了。比如view的旋轉(zhuǎn),放大,縮小。
15、Android中跨進(jìn)程通訊的幾種方式
Android 跨進(jìn)程通信,像intent,contentProvider,廣播,service都可以跨進(jìn)程通信。
intent:這種跨進(jìn)程方式并不是訪問(wèn)內(nèi)存的形式,它需要傳遞一個(gè)uri,比如說(shuō)打電話。
contentProvider:這種形式,是使用數(shù)據(jù)共享的形式進(jìn)行數(shù)據(jù)共享。
service:遠(yuǎn)程服務(wù),aidl
廣播
16、AIDL理解
此處延伸:簡(jiǎn)述Binder
AIDL: 每一個(gè)進(jìn)程都有自己的Dalvik VM實(shí)例,都有自己的一塊獨(dú)立的內(nèi)存,都在自己的內(nèi)存上存儲(chǔ)自己的數(shù)據(jù),執(zhí)行著自己的操作,都在自己的那片狹小的空間里過(guò)完自己的一生。而aidl就類似與兩個(gè)進(jìn)程之間的橋梁,使得兩個(gè)進(jìn)程之間可以進(jìn)行數(shù)據(jù)的傳輸,跨進(jìn)程通信有多種選擇,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系統(tǒng)資源比較多,如果是頻繁的跨進(jìn)程通信的話顯然是不可取的;Messenger 進(jìn)行跨進(jìn)程通信時(shí)請(qǐng)求隊(duì)列是同步進(jìn)行的,無(wú)法并發(fā)執(zhí)行。
Binde機(jī)制簡(jiǎn)單理解:
在Android系統(tǒng)的Binder機(jī)制中,是有Client,Service,ServiceManager,Binder驅(qū)動(dòng)程序組成的,其中Client,service,Service Manager運(yùn)行在用戶空間,Binder驅(qū)動(dòng)程序是運(yùn)行在內(nèi)核空間的。而Binder就是把這4種組件粘合在一塊的粘合劑,其中核心的組件就是Binder驅(qū)動(dòng)程序,Service Manager提供輔助管理的功能,而Client和Service正是在Binder驅(qū)動(dòng)程序和Service Manager提供的基礎(chǔ)設(shè)施上實(shí)現(xiàn)C/S 之間的通信。其中Binder驅(qū)動(dòng)程序提供設(shè)備文件/dev/binder與用戶控件進(jìn)行交互,
Client、Service,Service Manager通過(guò)open和ioctl文件操作相應(yīng)的方法與Binder驅(qū)動(dòng)程序進(jìn)行通信。而Client和Service之間的進(jìn)程間通信是通過(guò)Binder驅(qū)動(dòng)程序間接實(shí)現(xiàn)的。而Binder Manager是一個(gè)守護(hù)進(jìn)程,用來(lái)管理Service,并向Client提供查詢Service接口的能力。
17、Handler的原理
Android中主線程是不能進(jìn)行耗時(shí)操作的,子線程是不能進(jìn)行更新UI的。所以就有了handler,它的作用就是實(shí)現(xiàn)線程之間的通信。
handler整個(gè)流程中,主要有四個(gè)對(duì)象,handler,Message,MessageQueue,Looper。當(dāng)應(yīng)用創(chuàng)建的時(shí)候,就會(huì)在主線程中創(chuàng)建handler對(duì)象,
我們通過(guò)要傳送的消息保存到Message中,handler通過(guò)調(diào)用sendMessage方法將Message發(fā)送到MessageQueue中,Looper對(duì)象就會(huì)不斷的調(diào)用loop()方法
不斷的從MessageQueue中取出Message交給handler進(jìn)行處理。從而實(shí)現(xiàn)線程之間的通信。
18、Binder機(jī)制原理
在Android系統(tǒng)的Binder機(jī)制中,是有Client,Service,ServiceManager,Binder驅(qū)動(dòng)程序組成的,其中Client,service,Service Manager運(yùn)行在用戶空間,Binder驅(qū)動(dòng)程序是運(yùn)行在內(nèi)核空間的。而Binder就是把這4種組件粘合在一塊的粘合劑,其中核心的組件就是Binder驅(qū)動(dòng)程序,Service Manager提供輔助管理的功能,而Client和Service正是在Binder驅(qū)動(dòng)程序和Service Manager提供的基礎(chǔ)設(shè)施上實(shí)現(xiàn)C/S 之間的通信。其中Binder驅(qū)動(dòng)程序提供設(shè)備文件/dev/binder與用戶控件進(jìn)行交互,Client、Service,Service Manager通過(guò)open和ioctl文件操作相應(yīng)的方法與Binder驅(qū)動(dòng)程序進(jìn)行通信。而Client和Service之間的進(jìn)程間通信是通過(guò)Binder驅(qū)動(dòng)程序間接實(shí)現(xiàn)的。而Binder Manager是一個(gè)守護(hù)進(jìn)程,用來(lái)管理Service,并向Client提供查詢Service接口的能力。
19、熱修復(fù)的原理
我們知道Java虛擬機(jī) —— JVM 是加載類的class文件的,而Android虛擬機(jī)——Dalvik/ART VM 是加載類的dex文件,
而他們加載類的時(shí)候都需要ClassLoader,ClassLoader有一個(gè)子類BaseDexClassLoader,而BaseDexClassLoader下有一個(gè)
數(shù)組——DexPathList,是用來(lái)存放dex文件,當(dāng)BaseDexClassLoader通過(guò)調(diào)用findClass方法時(shí),實(shí)際上就是遍歷數(shù)組,
找到相應(yīng)的dex文件,找到,則直接將它return。而熱修復(fù)的解決方法就是將新的dex添加到該集合中,并且是在舊的dex的前面,
所以就會(huì)優(yōu)先被取出來(lái)并且return返回。
20、Android內(nèi)存泄露及管理
(1)內(nèi)存溢出(OOM)和內(nèi)存泄露(對(duì)象無(wú)法被回收)的區(qū)別。
(2)引起內(nèi)存泄露的原因
(3) 內(nèi)存泄露檢測(cè)工具 ------>LeakCanary
內(nèi)存溢出 out of memory:是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請(qǐng)了一個(gè)integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。內(nèi)存溢出通俗的講就是內(nèi)存不夠用。
內(nèi)存泄露 memory leak:是指程序在申請(qǐng)內(nèi)存后,無(wú)法釋放已申請(qǐng)的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無(wú)論多少內(nèi)存,遲早會(huì)被占光
內(nèi)存泄露原因:
一、Handler 引起的內(nèi)存泄漏。
解決:將Handler聲明為靜態(tài)內(nèi)部類,就不會(huì)持有外部類SecondActivity的引用,其生命周期就和外部類無(wú)關(guān),
如果Handler里面需要context的話,可以通過(guò)弱引用方式引用外部類
二、單例模式引起的內(nèi)存泄漏。
解決:Context是ApplicationContext,由于ApplicationContext的生命周期是和app一致的,不會(huì)導(dǎo)致內(nèi)存泄漏
三、非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實(shí)例引起的內(nèi)存泄漏。
解決:把內(nèi)部類修改為靜態(tài)的就可以避免內(nèi)存泄漏了
四、非靜態(tài)匿名內(nèi)部類引起的內(nèi)存泄漏。
解決:將匿名內(nèi)部類設(shè)置為靜態(tài)的。
五、注冊(cè)/反注冊(cè)未成對(duì)使用引起的內(nèi)存泄漏。
注冊(cè)廣播接受器、EventBus等,記得解綁。
六、資源對(duì)象沒有關(guān)閉引起的內(nèi)存泄漏。
在這些資源不使用的時(shí)候,記得調(diào)用相應(yīng)的類似close()、destroy()、recycler()、release()等方法釋放。
七、集合對(duì)象沒有及時(shí)清理引起的內(nèi)存泄漏。
通常會(huì)把一些對(duì)象裝入到集合中,當(dāng)不使用的時(shí)候一定要記得及時(shí)清理集合,讓相關(guān)對(duì)象不再被引用。
21、Fragment與Fragment、Activity通信的方式
1.直接在一個(gè)Fragment中調(diào)用另外一個(gè)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 測(cè)試分析耗時(shí)的)
App啟動(dòng)優(yōu)化
布局優(yōu)化
響應(yīng)優(yōu)化
內(nèi)存優(yōu)化
電池使用優(yōu)化
網(wǎng)絡(luò)優(yōu)化
App啟動(dòng)優(yōu)化(針對(duì)冷啟動(dòng))
App啟動(dòng)的方式有三種:
冷啟動(dòng):App沒有啟動(dòng)過(guò)或App進(jìn)程被killed, 系統(tǒng)中不存在該App進(jìn)程, 此時(shí)啟動(dòng)App即為冷啟動(dòng)。
熱啟動(dòng):熱啟動(dòng)意味著你的App進(jìn)程只是處于后臺(tái), 系統(tǒng)只是將其從后臺(tái)帶到前臺(tái), 展示給用戶。
介于冷啟動(dòng)和熱啟動(dòng)之間, 一般來(lái)說(shuō)在以下兩種情況下發(fā)生:
(1)用戶back退出了App, 然后又啟動(dòng). App進(jìn)程可能還在運(yùn)行, 但是activity需要重建。
(2)用戶退出App后, 系統(tǒng)可能由于內(nèi)存原因?qū)pp殺死, 進(jìn)程和activity都需要重啟, 但是可以在onCreate中將被動(dòng)殺死鎖保存的狀態(tài)(saved instance state)恢復(fù)。
優(yōu)化:
Application的onCreate(特別是第三方SDK初始化),首屏Activity的渲染都不要進(jìn)行耗時(shí)操作,如果有,就可以放到子線程或者IntentService中
布局優(yōu)化
盡量不要過(guò)于復(fù)雜的嵌套??梢允褂?lt;include>,<merge>,<ViewStub>
響應(yīng)優(yōu)化
Android系統(tǒng)每隔16ms會(huì)發(fā)出VSYNC信號(hào)重繪我們的界面(Activity)。
頁(yè)面卡頓的原因:
(1)過(guò)于復(fù)雜的布局.
(2)UI線程的復(fù)雜運(yùn)算
(3)頻繁的GC,導(dǎo)致頻繁GC有兩個(gè)原因:1、內(nèi)存抖動(dòng), 即大量的對(duì)象被創(chuàng)建又在短時(shí)間內(nèi)馬上被釋放.2、瞬間產(chǎn)生大量的對(duì)象會(huì)嚴(yán)重占用內(nèi)存區(qū)域。
內(nèi)存優(yōu)化:參考內(nèi)存泄露和內(nèi)存溢出部分
電池使用優(yōu)化(使用工具:Batterystats & bugreport)
(1)優(yōu)化網(wǎng)絡(luò)請(qǐng)求
(2)定位中使用GPS, 請(qǐng)記得及時(shí)關(guān)閉
網(wǎng)絡(luò)優(yōu)化(網(wǎng)絡(luò)連接對(duì)用戶的影響:流量,電量,用戶等待)可在Android studio下方logcat旁邊那個(gè)工具Network Monitor檢測(cè)
API設(shè)計(jì):App與Server之間的API設(shè)計(jì)要考慮網(wǎng)絡(luò)請(qǐng)求的頻次, 資源的狀態(tài)等. 以便App可以以較少的請(qǐng)求來(lái)完成業(yè)務(wù)需求和界面的展示.
Gzip壓縮:使用Gzip來(lái)壓縮request和response, 減少傳輸數(shù)據(jù)量, 從而減少流量消耗.
圖片的Size:可以在獲取圖片時(shí)告知服務(wù)器需要的圖片的寬高, 以便服務(wù)器給出合適的圖片, 避免浪費(fèi).
網(wǎng)絡(luò)緩存:適當(dāng)?shù)木彺? 既可以讓我們的應(yīng)用看起來(lái)更快, 也能避免一些不必要的流量消耗.
24、圖片優(yōu)化
(1)對(duì)圖片本身進(jìn)行操作。盡量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource來(lái)設(shè)置一張大圖,因?yàn)檫@些方法在完成decode后,
最終都是通過(guò)java層的createBitmap來(lái)完成的,需要消耗更多內(nèi)存.
(2)圖片進(jìn)行縮放的比例,SDK中建議其值是2的指數(shù)值,值越大會(huì)導(dǎo)致圖片不清晰。
(3)不用的圖片記得調(diào)用圖片的recycle()方法
25、HybridApp WebView和JS交互
Android與JS通過(guò)WebView互相調(diào)用方法,實(shí)際上是:
Android去調(diào)用JS的代碼
1. 通過(guò)WebView的loadUrl(),使用該方法比較簡(jiǎn)潔,方便。但是效率比較低,獲取返回值比較困難。
2. 通過(guò)WebView的evaluateJavascript(),該方法效率高,但是4.4以上的版本才支持,4.4以下版本不支持。所以建議兩者混合使用。
JS去調(diào)用Android的代碼
1. 通過(guò)WebView的addJavascriptInterface()進(jìn)行對(duì)象映射 ,該方法使用簡(jiǎn)單,僅將Android對(duì)象和JS對(duì)象映射即可,但是存在比較大的漏洞。
漏洞產(chǎn)生原因是:當(dāng)JS拿到Android這個(gè)對(duì)象后,就可以調(diào)用這個(gè)Android對(duì)象中所有的方法,包括系統(tǒng)類(java.lang.Runtime 類),從而進(jìn)行任意代碼執(zhí)行。
解決方式:
(1)Google 在Android 4.2 版本中規(guī)定對(duì)被調(diào)用的函數(shù)以 @JavascriptInterface進(jìn)行注解從而避免漏洞***。
(2)在Android 4.2版本之前采用攔截prompt()進(jìn)行漏洞修復(fù)。
2. 通過(guò) WebViewClient 的shouldOverrideUrlLoading ()方法回調(diào)攔截 url 。這種方式的優(yōu)點(diǎn):不存在方式1的漏洞;缺點(diǎn):JS獲取Android方法的返回值復(fù)雜。(ios主要用的是這個(gè)方式)
(1)Android通過(guò) WebViewClient 的回調(diào)方法shouldOverrideUrlLoading ()攔截 url
(2)解析該 url 的協(xié)議
(3)如果檢測(cè)到是預(yù)先約定好的協(xié)議,就調(diào)用相應(yīng)方法
3. 通過(guò) WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調(diào)攔截JS對(duì)話框alert()、confirm()、prompt() 消息
這種方式的優(yōu)點(diǎn):不存在方式1的漏洞;缺點(diǎn):JS獲取Android方法的返回值復(fù)雜。
26、JAVA GC原理
垃圾收集算法的核心思想是:對(duì)虛擬機(jī)可用內(nèi)存空間,即堆空間中的對(duì)象進(jìn)行識(shí)別,如果對(duì)象正在被引用,那么稱其為存活對(duì)象
,反之,如果對(duì)象不再被引用,則為垃圾對(duì)象,可以回收其占據(jù)的空間,用于再分配。垃圾收集算法的選擇和垃圾收集系統(tǒng)參數(shù)的合理調(diào)節(jié)直接影響著系統(tǒng)性能。
27、ANR
ANR全名Application Not Responding, 也就是"應(yīng)用無(wú)響應(yīng)". 當(dāng)操作在一段時(shí)間內(nèi)系統(tǒng)無(wú)法處理時(shí), 系統(tǒng)層面會(huì)彈出上圖那樣的ANR對(duì)話框.
產(chǎn)生原因:
(1)5s內(nèi)無(wú)法響應(yīng)用戶輸入事件(例如鍵盤輸入, 觸摸屏幕等).
(2)BroadcastReceiver在10s內(nèi)無(wú)法結(jié)束
(3)Service 20s內(nèi)無(wú)法結(jié)束(低概率)
解決方式:
(1)不要在主線程中做耗時(shí)的操作,而應(yīng)放在子線程中來(lái)實(shí)現(xiàn)。如onCreate()和onResume()里盡可能少的去做創(chuàng)建操作。
(2)應(yīng)用程序應(yīng)該避免在BroadcastReceiver里做耗時(shí)的操作或計(jì)算。
(3)避免在Intent Receiver里啟動(dòng)一個(gè)Activity,因?yàn)樗鼤?huì)創(chuàng)建一個(gè)新的畫面,并從當(dāng)前用戶正在運(yùn)行的程序上搶奪焦點(diǎn)。
(4)service是運(yùn)行在主線程的,所以在service中做耗時(shí)操作,必須要放在子線程中。
28、設(shè)計(jì)模式
此處延伸:Double Check的寫法被要求寫出來(lái)。
單例模式:分為惡漢式和懶漢式
惡漢式:
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)勢(shì)
MVP模式,對(duì)應(yīng)著Model--業(yè)務(wù)邏輯和實(shí)體模型,view--對(duì)應(yīng)著activity,負(fù)責(zé)View的繪制以及與用戶交互,Presenter--負(fù)責(zé)View和Model之間的交互,MVP模式是在MVC模式的基礎(chǔ)上,將Model與View徹底分離使得項(xiàng)目的耦合性更低,在Mvc中項(xiàng)目中的activity對(duì)應(yīng)著mvc中的C--Controllor,而項(xiàng)目中的邏輯處理都是在這個(gè)C中處理,同時(shí)View與Model之間的交互,也是也就是說(shuō),mvc中所有的邏輯交互和用戶交互,都是放在Controllor中,也就是activity中。View和model是可以直接通信的。而MVP模式則是分離的更加徹底,分工更加明確Model--業(yè)務(wù)邏輯和實(shí)體模型,view--負(fù)責(zé)與用戶交互,Presenter 負(fù)責(zé)完成View于Model間的交互,MVP和MVC最大的區(qū)別是MVC中是允許Model和View進(jìn)行交互的,而MVP中很明顯,Model與View之間的交互由Presenter完成。還有一點(diǎn)就是Presenter與View之間的交互是通過(guò)接口的
31、手寫算法(選擇冒泡必須要會(huì))
32、JNI
(1)安裝和下載Cygwin,下載 Android NDK
(2)在ndk項(xiàng)目中JNI接口的設(shè)計(jì)
(3)使用C/C++實(shí)現(xiàn)本地方法
(4)JNI生成動(dòng)態(tài)鏈接庫(kù).so文件
(5)將動(dòng)態(tài)鏈接庫(kù)復(fù)制到j(luò)ava工程,在java工程中調(diào)用,運(yùn)行java工程即可
33、RecyclerView和ListView的區(qū)別
RecyclerView可以完成ListView,GridView的效果,還可以完成瀑布流的效果。同時(shí)還可以設(shè)置列表的滾動(dòng)方向(垂直或者水平);
RecyclerView中view的復(fù)用不需要開發(fā)者自己寫代碼,系統(tǒng)已經(jīng)幫封裝完成了。
RecyclerView可以進(jìn)行局部刷新。
RecyclerView提供了API來(lái)實(shí)現(xiàn)item的動(dòng)畫效果。
在性能上:
如果需要頻繁的刷新數(shù)據(jù),需要添加動(dòng)畫,則RecyclerView有較大的優(yōu)勢(shì)。
如果只是作為列表展示,則兩者區(qū)別并不是很大。
34、Universal-ImageLoader,Picasso,F(xiàn)resco,Glide對(duì)比
Fresco 是 Facebook 推出的開源圖片緩存工具,主要特點(diǎn)包括:兩個(gè)內(nèi)存緩存加上 Native 緩存構(gòu)成了三級(jí)緩存,
優(yōu)點(diǎn):
1. 圖片存儲(chǔ)在安卓系統(tǒng)的匿名共享內(nèi)存, 而不是虛擬機(jī)的堆內(nèi)存中, 圖片的中間緩沖數(shù)據(jù)也存放在本地堆內(nèi)存, 所以, 應(yīng)用程序有更多的內(nèi)存使用, 不會(huì)因?yàn)閳D片加載而導(dǎo)致oom, 同時(shí)也減少垃圾回收器頻繁調(diào)用回收 Bitmap 導(dǎo)致的界面卡頓, 性能更高。
2. 漸進(jìn)式加載 JPEG 圖片, 支持圖片從模糊到清晰加載。
3. 圖片可以以任意的中心點(diǎn)顯示在 ImageView, 而不僅僅是圖片的中心。
4. JPEG 圖片改變大小也是在 native 進(jìn)行的, 不是在虛擬機(jī)的堆內(nèi)存, 同樣減少 OOM。
5. 很好的支持 GIF 圖片的顯示。
缺點(diǎn):
1. 框架較大, 影響 Apk 體積
2. 使用較繁瑣
Universal-ImageLoader:(估計(jì)由于HttpClient被Google放棄,作者就放棄維護(hù)這個(gè)框架)
優(yōu)點(diǎn):
1.支持下載進(jìn)度監(jiān)聽
2.可以在 View 滾動(dòng)中暫停圖片加載,通過(guò) PauseOnScrollListener 接口可以在 View 滾動(dòng)中暫停圖片加載。
3.默認(rèn)實(shí)現(xiàn)多種內(nèi)存緩存算法 這幾個(gè)圖片緩存都可以配置緩存算法,不過(guò) ImageLoader 默認(rèn)實(shí)現(xiàn)了較多緩存算法,如 Size 最大先刪除、使用最少先刪除、最近最少使用、先進(jìn)先刪除、時(shí)間最長(zhǎng)先刪除等。
4.支持本地緩存文件名規(guī)則定義
Picasso 優(yōu)點(diǎn)
1. 自帶統(tǒng)計(jì)監(jiān)控功能。支持圖片緩存使用的監(jiān)控,包括緩存命中率、已使用內(nèi)存大小、節(jié)省的流量等。
2.支持優(yōu)先級(jí)處理。每次任務(wù)調(diào)度前會(huì)選擇優(yōu)先級(jí)高的任務(wù),比如 App 頁(yè)面中 Banner 的優(yōu)先級(jí)高于 Icon 時(shí)就很適用。
3.支持延遲到圖片尺寸計(jì)算完成加載
4.支持飛行模式、并發(fā)線程數(shù)根據(jù)網(wǎng)絡(luò)類型而變。 手機(jī)切換到飛行模式或網(wǎng)絡(luò)類型變換時(shí)會(huì)自動(dòng)調(diào)整線程池最大并發(fā)數(shù),比如 wifi 最大并發(fā)為 4,4g 為 3,3g 為 2。 這里 Picasso 根據(jù)網(wǎng)絡(luò)類型來(lái)決定最大并發(fā)數(shù),而不是 CPU 核數(shù)。
5.“無(wú)”本地緩存。無(wú)”本地緩存,不是說(shuō)沒有本地緩存,而是 Picasso 自己沒有實(shí)現(xiàn),交給了 Square 的另外一個(gè)網(wǎng)絡(luò)庫(kù) okhttp 去實(shí)現(xiàn),這樣的好處是可以通過(guò)請(qǐng)求 Response Header 中的 Cache-Control 及 Expired 控制圖片的過(guò)期時(shí)間。
Glide 優(yōu)點(diǎn)
1. 不僅僅可以進(jìn)行圖片緩存還可以緩存媒體文件。Glide 不僅是一個(gè)圖片緩存,它支持 Gif、WebP、縮略圖。甚至是 Video,所以更該當(dāng)做一個(gè)媒體緩存。
2. 支持優(yōu)先級(jí)處理。
3. 與 Activity/Fragment 生命周期一致,支持 trimMemory。Glide 對(duì)每個(gè) context 都保持一個(gè) RequestManager,通過(guò) FragmentTransaction 保持與 Activity/Fragment 生命周期一致,并且有對(duì)應(yīng)的 trimMemory 接口實(shí)現(xiàn)可供調(diào)用。
4. 支持 okhttp、Volley。Glide 默認(rèn)通過(guò) UrlConnection 獲取數(shù)據(jù),可以配合 okhttp 或是 Volley 使用。實(shí)際 ImageLoader、Picasso 也都支持 okhttp、Volley。
5. 內(nèi)存友好。Glide 的內(nèi)存緩存有個(gè) active 的設(shè)計(jì),從內(nèi)存緩存中取數(shù)據(jù)時(shí),不像一般的實(shí)現(xiàn)用 get,而是用 remove,再將這個(gè)緩存數(shù)據(jù)放到一個(gè) value 為軟引用的 activeResources map 中,并計(jì)數(shù)引用數(shù),在圖片加載完成后進(jìn)行判斷,如果引用計(jì)數(shù)為空則回收掉。內(nèi)存緩存更小圖片,Glide 以 url、view_width、view_height、屏幕的分辨率等做為聯(lián)合 key,將處理后的圖片緩存在內(nèi)存緩存中,而不是原始圖片以節(jié)省大小與 Activity/Fragment 生命周期一致,支持 trimMemory。圖片默認(rèn)使用默認(rèn) RGB_565 而不是 ARGB_888,雖然清晰度差些,但圖片更小,也可配置到 ARGB_888。
6.Glide 可以通過(guò) signature 或不使用本地緩存支持 url 過(guò)期
42、Xutils, OKhttp, Volley, Retrofit對(duì)比
Xutils這個(gè)框架非常全面,可以進(jìn)行網(wǎng)絡(luò)請(qǐng)求,可以進(jìn)行圖片加載處理,可以數(shù)據(jù)儲(chǔ)存,還可以對(duì)view進(jìn)行注解,使用這個(gè)框架非常方便,但是缺點(diǎn)也是非常明顯的,使用這個(gè)項(xiàng)目,會(huì)導(dǎo)致項(xiàng)目對(duì)這個(gè)框架依賴非常的嚴(yán)重,一旦這個(gè)框架出現(xiàn)問(wèn)題,那么對(duì)項(xiàng)目來(lái)說(shuō)影響非常大的。、
OKhttp:Android開發(fā)中是可以直接使用現(xiàn)成的api進(jìn)行網(wǎng)絡(luò)請(qǐng)求的。就是使用HttpClient,HttpUrlConnection進(jìn)行操作。okhttp針對(duì)Java和Android程序,封裝的一個(gè)高性能的http請(qǐng)求庫(kù),支持同步,異步,而且okhttp又封裝了線程池,封裝了數(shù)據(jù)轉(zhuǎn)換,封裝了參數(shù)的使用,錯(cuò)誤處理等。API使用起來(lái)更加的方便。但是我們?cè)陧?xiàng)目中使用的時(shí)候仍然需要自己在做一層封裝,這樣才能使用的更加的順手。
Volley:Volley是Google官方出的一套小而巧的異步請(qǐng)求庫(kù),該框架封裝的擴(kuò)展性很強(qiáng),支持HttpClient、HttpUrlConnection, 甚至支持OkHttp,而且Volley里面也封裝了ImageLoader,所以如果你愿意你甚至不需要使用圖片加載框架,不過(guò)這塊功能沒有一些專門的圖片加載框架強(qiáng)大,對(duì)于簡(jiǎn)單的需求可以使用,稍復(fù)雜點(diǎn)的需求還是需要用到專門的圖片加載框架。Volley也有缺陷,比如不支持post大數(shù)據(jù),所以不適合上傳文件。不過(guò)Volley設(shè)計(jì)的初衷本身也就是為頻繁的、數(shù)據(jù)量小的網(wǎng)絡(luò)請(qǐng)求而生。
Retrofit:Retrofit是Square公司出品的默認(rèn)基于OkHttp封裝的一套R(shí)ESTful網(wǎng)絡(luò)請(qǐng)求框架,RESTful是目前流行的一套api設(shè)計(jì)的風(fēng)格, 并不是標(biāo)準(zhǔn)。Retrofit的封裝可以說(shuō)是很強(qiáng)大,里面涉及到一堆的設(shè)計(jì)模式,可以通過(guò)注解直接配置請(qǐng)求,可以使用不同的http客戶端,雖然默認(rèn)是用http ,可以使用不同Json Converter 來(lái)序列化數(shù)據(jù),同時(shí)提供對(duì)RxJava的支持,使用Retrofit + OkHttp + RxJava + Dagger2 可以說(shuō)是目前比較潮的一套框架,但是需要有比較高的門檻。
Volley VS OkHttp
Volley的優(yōu)勢(shì)在于封裝的更好,而使用OkHttp你需要有足夠的能力再進(jìn)行一次封裝。而OkHttp的優(yōu)勢(shì)在于性能更高,因?yàn)?OkHttp基于NIO和Okio ,所以性能上要比 Volley更快。IO 和 NIO這兩個(gè)都是Java中的概念,如果我從硬盤讀取數(shù)據(jù),第一種方式就是程序一直等,數(shù)據(jù)讀完后才能繼續(xù)操作這種是最簡(jiǎn)單的也叫阻塞式IO,還有一種是你讀你的,程序接著往下執(zhí)行,等數(shù)據(jù)處理完你再來(lái)通知我,然后再處理回調(diào)。而第二種就是 NIO 的方式,非阻塞式, 所以NIO當(dāng)然要比IO的性能要好了,而 Okio是 Square 公司基于IO和NIO基礎(chǔ)上做的一個(gè)更簡(jiǎn)單、高效處理數(shù)據(jù)流的一個(gè)庫(kù)。理論上如果Volley和OkHttp對(duì)比的話,更傾向于使用 Volley,因?yàn)閂olley內(nèi)部同樣支持使用OkHttp,這點(diǎn)OkHttp的性能優(yōu)勢(shì)就沒了, 而且 Volley 本身封裝的也更易用,擴(kuò)展性更好些。
OkHttp VS Retrofit
毫無(wú)疑問(wèn),Retrofit 默認(rèn)是基于 OkHttp 而做的封裝,這點(diǎn)來(lái)說(shuō)沒有可比性,肯定首選 Retrofit。
Volley VS Retrofit
這兩個(gè)庫(kù)都做了不錯(cuò)的封裝,但Retrofit解耦的更徹底,尤其Retrofit2.0出來(lái),Jake對(duì)之前1.0設(shè)計(jì)不合理的地方做了大量重構(gòu), 職責(zé)更細(xì)分,而且Retrofit默認(rèn)使用OkHttp,性能上也要比Volley占優(yōu)勢(shì),再有如果你的項(xiàng)目如果采用了RxJava ,那更該使用 Retrofit 。所以這兩個(gè)庫(kù)相比,Retrofit更有優(yōu)勢(shì),在能掌握兩個(gè)框架的前提下該優(yōu)先使用 Retrofit。但是Retrofit門檻要比Volley稍高些,要理解他的原理,各種用法,想徹底搞明白還是需要花些功夫的,如果你對(duì)它一知半解,那還是建議在商業(yè)項(xiàng)目使用Volley吧。
Java
1、線程中sleep和wait的區(qū)別
(1)這兩個(gè)方法來(lái)自不同的類,sleep是來(lái)自Thread,wait是來(lái)自O(shè)bject;
(2)sleep方法沒有釋放鎖,而wait方法釋放了鎖。
(3)wait,notify,notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用。
2、Thread中的start()和run()方法有什么區(qū)別
start()方法是用來(lái)啟動(dòng)新創(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變量:對(duì)于靜態(tài)變量在內(nèi)存中只有一個(gè)拷貝(節(jié)省內(nèi)存),JVM只為靜態(tài)分配一次內(nèi)存,
在加載類的過(guò)程中完成靜態(tài)變量的內(nèi)存分配,可用類名直接訪問(wèn)(方便),當(dāng)然也可以通過(guò)對(duì)象來(lái)訪問(wèn)(但是這是不推薦的)。
2、static代碼塊
static代碼塊是類加載時(shí),初始化自動(dòng)執(zhí)行的。
3、static方法
static方法可以直接通過(guò)類名調(diào)用,任何的實(shí)例也都可以調(diào)用,因此static方法中不能用this和super關(guān)鍵字,
不能直接訪問(wèn)所屬類的實(shí)例變量和實(shí)例方法(就是不帶static的成員變量和成員成員方法),只能訪問(wèn)所屬類的靜態(tài)成員變量和成員方法。
4、String,StringBuffer,StringBuilder區(qū)別
1、三者在執(zhí)行速度上:StringBuilder > StringBuffer > String (由于String是常量,不可改變,拼接時(shí)會(huì)重新創(chuàng)建新的對(duì)象)。
2、StringBuffer是線程安全的,StringBuilder是線程不安全的。(由于StringBuffer有緩沖區(qū))
5、Java中重載和重寫的區(qū)別:
1、重載:一個(gè)類中可以有多個(gè)相同方法名的,但是參數(shù)類型和個(gè)數(shù)都不一樣。這是重載。
2、重寫:子類繼承父類,則子類可以通過(guò)實(shí)現(xiàn)父類中的方法,從而新的方法把父類舊的方法覆蓋。
6、Http https區(qū)別
此處延伸:https的實(shí)現(xiàn)原理
1、https協(xié)議需要到ca申請(qǐng)證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用。
2、http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
4、http的連接很簡(jiǎn)單,是無(wú)狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
https實(shí)現(xiàn)原理:
(1)客戶使用https的URL訪問(wèn)Web服務(wù)器,要求與Web服務(wù)器建立SSL連接。
(2)Web服務(wù)器收到客戶端請(qǐng)求后,會(huì)將網(wǎng)站的證書信息(證書中包含公鑰)傳送一份給客戶端。
(3)客戶端的瀏覽器與Web服務(wù)器開始協(xié)商SSL連接的安全等級(jí),也就是信息加密的等級(jí)。
(4)客戶端的瀏覽器根據(jù)雙方同意的安全等級(jí),建立會(huì)話密鑰,然后利用網(wǎng)站的公鑰將會(huì)話密鑰加密,并傳送給網(wǎng)站。
(5)Web服務(wù)器利用自己的私鑰解密出會(huì)話密鑰。
(6)Web服務(wù)器利用會(huì)話密鑰加密與客戶端之間的通信。
7、Http位于TCP/IP模型中的第幾層?為什么說(shuō)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é)議的,所以說(shuō)http是可靠的數(shù)據(jù)傳輸協(xié)議。
8、HTTP鏈接的特點(diǎn)
HTTP連接最顯著的特點(diǎn)是客戶端發(fā)送的每次請(qǐng)求都需要服務(wù)器回送響應(yīng),在請(qǐng)求結(jié)束后,會(huì)主動(dòng)釋放連接。
從建立連接到關(guān)閉連接的過(guò)程稱為“一次連接”。
9、TCP和UDP的區(qū)別
tcp是面向連接的,由于tcp連接需要三次握手,所以能夠最低限度的降低風(fēng)險(xiǎn),保證連接的可靠性。
udp 不是面向連接的,udp建立連接前不需要與對(duì)象建立連接,無(wú)論是發(fā)送還是接收,都沒有發(fā)送確認(rèn)信號(hào)。所以說(shuō)udp是不可靠的。
由于udp不需要進(jìn)行確認(rèn)連接,使得UDP的開銷更小,傳輸速率更高,所以實(shí)時(shí)行更好。
10、Socket建立網(wǎng)絡(luò)連接的步驟
建立Socket連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行與客戶端--ClientSocket,一個(gè)運(yùn)行于服務(wù)端--ServiceSocket
1、服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請(qǐng)求。
2、客戶端請(qǐng)求:指客戶端的套接字提出連接請(qǐng)求,要連接的目標(biāo)是服務(wù)器端的套接字。注意:客戶端的套接字必須描述他要連接的服務(wù)器的套接字,
指出服務(wù)器套接字的地址和端口號(hào),然后就像服務(wù)器端套接字提出連接請(qǐng)求。
3、連接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽到客戶端套接字的連接請(qǐng)求時(shí),就響應(yīng)客戶端套接字的請(qǐng)求,建立一個(gè)新的線程,把服務(wù)器端套接字的描述
發(fā)給客戶端,一旦客戶端確認(rèn)了此描述,雙方就正式建立連接。而服務(wù)端套接字則繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請(qǐng)求。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。