1瘪菌、RecyclerView和ListView的區(qū)別
緩存上:前者緩存的是View+ViewHolder+flag崎坊,不用每次調(diào)用findViewById,后者則只是緩存View
刷新數(shù)據(jù)方面,前者提供了局部刷新绑咱,后者則全部刷新
2蔚约、recyclerView嵌套卡頓解決如何解決
設(shè)置預(yù)加載的數(shù)量LinearLayoutManager.setInitialPrefetchItemCount(4)吃媒,默認(rèn)是預(yù)加載2個(gè)衡奥,
設(shè)置子項(xiàng)緩存爹袁,
設(shè)置自帶滑動(dòng)沖突解決屬性rv.setHasFixedSize(true);? ? ??
? rv.setNestedScrollingEnabled(false);
可以完美解決,不過Google不推薦RecyClerView嵌套使用,需要嵌套盡量找類似于ExpandableListView 第三方控件來解決
3矮固、談MVC 失息,MVP,MVVM
MVC:View是可以直接訪問Model的档址!從而盹兢,View里會(huì)包含Model信息,不可避免的還要包括一些 業(yè)務(wù)邏輯守伸。 在MVC模型里蛤迎,更關(guān)注的Model的不變,而同時(shí)有多個(gè)對(duì)Model的不同顯示含友,及View替裆。所以,在MVC模型里窘问,Model不依賴于View辆童,但是 View是依賴于Model的。不僅如此惠赫,因?yàn)橛幸恍I(yè)務(wù)邏輯在View里實(shí)現(xiàn)了把鉴,導(dǎo)致要更改View也是比較困難的,至少那些業(yè)務(wù)邏輯是無法重用的儿咱。
MVP:MVP 是從經(jīng)典的模式MVC演變而來庭砍,它們的基本思想有相通的地方:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù)混埠,View負(fù) 責(zé)顯示怠缸。作為一種新的模式,MVP與MVC有著一個(gè)重大的區(qū)別:在MVP中View并不直接使用Model钳宪,它們之間的通信是通過Presenter (MVC中的Controller)來進(jìn)行的揭北,所有的交互都發(fā)生在Presenter內(nèi)部,而在MVC中View會(huì)從直接Model中讀取數(shù)據(jù)而不是通過 Controller吏颖。
MVVM:數(shù)據(jù)雙向綁定搔体,通過數(shù)據(jù)驅(qū)動(dòng)UI,M提供數(shù)據(jù)半醉,V視圖疚俱,VM即數(shù)據(jù)驅(qū)動(dòng)層
4 、Android性能優(yōu)化
布局優(yōu)化: 減少布局層級(jí)缩多,使用ViewStub提高顯示速度呆奕,布局服用夯尽,盡可能少使用warp_content,刪除空間中無用的屬性,避免過度繪制移除window默認(rèn)背景登馒,按需顯示展位圖匙握,自定義View優(yōu)化,使用canvas.clipRect()識(shí)別可見區(qū)域
啟動(dòng)速度:采用分布加載陈轿,異步加載圈纺,延期加載提高應(yīng)用初始化速度,采用線程初始化數(shù)據(jù)等麦射,合理的刷新機(jī)制
內(nèi)存方面:防止內(nèi)存泄露,使用一些第三方工具檢測解決
代碼優(yōu)化:遵循Java生命周期
安裝包優(yōu)化:刪除無用資源蛾娶,優(yōu)化圖片,代碼混淆潜秋,避免重復(fù)庫存在蛔琅,插件化
5、Fragment中add與replace的區(qū)別峻呛?
add不會(huì)重新初始化fragment,replace每次都會(huì)罗售;
添加相同的fragment時(shí),replace不會(huì)有任何變化钩述,add會(huì)報(bào)IllegalStateException 異常寨躁;
replace 先 remove 掉相同 id 的所有 fragment,然后在add 當(dāng)前的這個(gè) fragment牙勘,而 add 是覆蓋前一個(gè)fragment职恳。所以如果使用 add 一般會(huì)伴隨 hide()和show(),避免布局重疊方面;
使用 add放钦,如果應(yīng)用放在后臺(tái),或以其他方式被系統(tǒng)銷毀恭金,再打開時(shí)操禀,hide()中引用的 fragment 會(huì)銷毀,所以依然會(huì)出現(xiàn)布局重疊 bug蔚叨,可以使用 replace 或使用 add時(shí)床蜘,添加一個(gè) tag 參數(shù);
6蔑水、如何避免OOM?
1.使用更加輕量的數(shù)據(jù)結(jié)構(gòu):如使用ArrayMap/SparseArray替代HashMap,HashMap更耗內(nèi)存,因?yàn)樗枰~外的實(shí)例對(duì)象來記錄Mapping操作扬蕊,SparseArray更加高效搀别,因?yàn)樗苊饬薑ey Value的自動(dòng)裝箱,和裝箱后的解箱操作
2.便面枚舉的使用尾抑,可以用靜態(tài)常量或者注解@IntDef替代
3.Bitmap優(yōu)化:
a.尺寸壓縮:通過InSampleSize設(shè)置合適的縮放
b.顏色質(zhì)量:設(shè)置合適的format歇父,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6蒂培,存在很大差異
c.inBitmap:使用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經(jīng)存在的內(nèi)存區(qū)域,新解碼的Bitmap會(huì)嘗試去使用之前那張Bitmap在Heap中所占據(jù)的pixel data內(nèi)存區(qū)域榜苫,而不是去問內(nèi)存重新申請(qǐng)一塊區(qū)域來存放Bitmap护戳。利用這種特性,即使是上千張的圖片垂睬,也只會(huì)僅僅只需要占用屏幕所能夠顯示的圖片數(shù)量的內(nèi)存大小媳荒,但復(fù)用存在一些限制,具體體現(xiàn)在:在Android 4.4之前只能重用相同大小的Bitmap的內(nèi)存驹饺,而Android 4.4及以后版本則只要后來的Bitmap比之前的小即可钳枕。使用inBitmap參數(shù)前,每創(chuàng)建一個(gè)Bitmap對(duì)象都會(huì)分配一塊內(nèi)存供其使用赏壹,而使用了inBitmap參數(shù)后鱼炒,多個(gè)Bitmap可以復(fù)用一塊內(nèi)存,這樣可以提高性能
4.StringBuilder替代String: 在有些時(shí)候蝌借,代碼中會(huì)需要使用到大量的字符串拼接的操作昔瞧,這種時(shí)候有必要考慮使用StringBuilder來替代頻繁的“+”
5.避免在類似onDraw這樣的方法中創(chuàng)建對(duì)象,因?yàn)樗鼤?huì)迅速占用大量內(nèi)存菩佑,引起頻繁的GC甚至內(nèi)存抖動(dòng)
6.減少內(nèi)存泄漏也是一種避免OOM的方法
7硬爆、如何實(shí)現(xiàn)進(jìn)程保活
a: Service 設(shè)置成 START_STICKY kill 后會(huì)被重啟(等待5秒左右)擎鸠,重傳Intent缀磕,保持與重啟前一樣
b: 通過 startForeground將進(jìn)程設(shè)置為前臺(tái)進(jìn)程, 做前臺(tái)服務(wù)劣光,優(yōu)先級(jí)和前臺(tái)應(yīng)用一個(gè)級(jí)別袜蚕,除非在系統(tǒng)內(nèi)存非常缺,否則此進(jìn)程不會(huì)被 kill
c: 雙進(jìn)程Service: 讓2個(gè)進(jìn)程互相保護(hù)對(duì)方绢涡,其中一個(gè)Service被清理后牲剃,另外沒被清理的進(jìn)程可以立即重啟進(jìn)程
d: 用C編寫守護(hù)進(jìn)程(即子進(jìn)程) : Android系統(tǒng)中當(dāng)前進(jìn)程(Process)fork出來的子進(jìn)程,被系統(tǒng)認(rèn)為是兩個(gè)不同的進(jìn)程雄可。當(dāng)父進(jìn)程被殺死的時(shí)候凿傅,子進(jìn)程仍然可以存活,并不受影響(Android5.0以上的版本不可行)聯(lián)系廠商数苫,加入白名單
e.鎖屏狀態(tài)下聪舒,開啟一個(gè)一像素Activity
8、說下冷啟動(dòng)與熱啟動(dòng)是什么虐急,區(qū)別箱残,如何優(yōu)化,使用場景等。
app冷啟動(dòng): 當(dāng)應(yīng)用啟動(dòng)時(shí)被辑,后臺(tái)沒有該應(yīng)用的進(jìn)程燎悍,這時(shí)系統(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給該應(yīng)用, 這個(gè)啟動(dòng)方式就叫做冷啟動(dòng)(后臺(tái)不存在該應(yīng)用進(jìn)程)盼理。冷啟動(dòng)因?yàn)橄到y(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給它谈山,所以會(huì)先創(chuàng)建和初始化Application類,再創(chuàng)建和初始化MainActivity類(包括一系列的測量宏怔、布局奏路、繪制),最后顯示在界面上举哟。
app熱啟動(dòng): 當(dāng)應(yīng)用已經(jīng)被打開思劳, 但是被按下返回鍵、Home鍵等按鍵時(shí)回到桌面或者是其他程序的時(shí)候妨猩,再重新打開該app時(shí)潜叛, 這個(gè)方式叫做熱啟動(dòng)(后臺(tái)已經(jīng)存在該應(yīng)用進(jìn)程)。熱啟動(dòng)因?yàn)闀?huì)從已有的進(jìn)程中來啟動(dòng)壶硅,所以熱啟動(dòng)就不會(huì)走Application這步了威兜,而是直接走M(jìn)ainActivity(包括一系列的測量、布局庐椒、繪制)椒舵,所以熱啟動(dòng)的過程只需要?jiǎng)?chuàng)建和初始化一個(gè)MainActivity就行了,而不必創(chuàng)建和初始化Application
冷啟動(dòng)的流程
當(dāng)點(diǎn)擊app的啟動(dòng)圖標(biāo)時(shí)约谈,安卓系統(tǒng)會(huì)從Zygote進(jìn)程中fork創(chuàng)建出一個(gè)新的進(jìn)程分配給該應(yīng)用笔宿,之后會(huì)依次創(chuàng)建和初始化Application類、創(chuàng)建MainActivity類棱诱、加載主題樣式Theme中的windowBackground等屬性設(shè)置給MainActivity以及配置Activity層級(jí)上的一些屬性泼橘、再inflate布局、當(dāng)onCreate/onStart/onResume方法都走完了后最后才進(jìn)行contentView的measure/layout/draw顯示在界面上
冷啟動(dòng)的生命周期簡要流程::
Application構(gòu)造方法 –> attachBaseContext()–>onCreate –>Activity構(gòu)造方法 –> onCreate() –> 配置主體中的背景等操作 –>onStart() –> onResume() –> 測量迈勋、布局炬灭、繪制顯示
冷啟動(dòng)的優(yōu)化主要是視覺上的優(yōu)化,解決白屏問題靡菇,提高用戶體驗(yàn)重归,所以通過上面冷啟動(dòng)的過程。能做的優(yōu)化如下:
減少 onCreate()方法的工作量
不要讓 Application 參與業(yè)務(wù)的操作
不要在 Application 進(jìn)行耗時(shí)操作
不要以靜態(tài)變量的方式在 Application 保存數(shù)據(jù)
減少布局的復(fù)雜度和層級(jí)
減少主線程耗時(shí)
為什么冷啟動(dòng)會(huì)有白屏黑屏問題厦凤?原因在于加載主題樣式Theme中的windowBackground等屬性設(shè)置給MainActivity發(fā)生在inflate布局當(dāng)onCreate/onStart/onResume方法之前鼻吮,而windowBackground背景被設(shè)置成了白色或者黑色,所以我們進(jìn)入app的第一個(gè)界面的時(shí)候會(huì)造成先白屏或黑屏一下再進(jìn)入界面泳唠。解決思路如下
1.給他設(shè)置 windowBackground 背景跟啟動(dòng)頁的背景相同狈网,如果你的啟動(dòng)頁是張圖片那么可以直接給 windowBackground 這個(gè)屬性設(shè)置該圖片那么就不會(huì)有一閃的效果了
<style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`
? ? <item name=``"android:windowBackground"``>@drawable/splash_bg</item>`
? ? <item name=``"android:windowNoTitle"``>``true``</item>`
</style>`
2.采用世面的處理方法,設(shè)置背景是透明的笨腥,給人一種延遲啟動(dòng)的感覺拓哺。,將背景顏色設(shè)置為透明色,這樣當(dāng)用戶點(diǎn)擊桌面APP圖片的時(shí)候,并不會(huì)"立即"進(jìn)入APP脖母,而且在桌面上停留一會(huì)士鸥,其實(shí)這時(shí)候APP已經(jīng)是啟動(dòng)的了,只是我們心機(jī)的把Theme里的windowBackground 的顏色設(shè)置成透明的谆级,強(qiáng)行把鍋甩給了手機(jī)應(yīng)用廠商(手機(jī)反應(yīng)太慢了啦)
<style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`
? ? <item name=``"android:windowIsTranslucent"``>``true``</item>`
? ? <item name=``"android:windowNoTitle"``>``true``</item>`
</style>`
3.以上兩種方法是在視覺上顯得更快烤礁,但其實(shí)只是一種表象,讓應(yīng)用啟動(dòng)的更快肥照,有一種思路脚仔,將 Application 中的不必要的初始化動(dòng)作實(shí)現(xiàn)懶加載,比如舆绎,在SpashActivity 顯示后再發(fā)送消息到 Application鲤脏,去初始化,這樣可以將初始化的動(dòng)作放在后邊吕朵,縮短應(yīng)用啟動(dòng)到用戶看到界面的時(shí)間
9猎醇、wait和 sleep 的區(qū)別
wait是Object的方法,wait是對(duì)象鎖努溃,鎖定方法不讓繼續(xù)執(zhí)行硫嘶,當(dāng)執(zhí)行notify方法后就會(huì)繼續(xù)執(zhí)行,sleep 是Thread的方法梧税,sleep 是使線程睡眠沦疾,讓出cpu,結(jié)束后自動(dòng)繼續(xù)執(zhí)行
10第队、String,StringBuffer,StringBuilder的區(qū)別
String不可改變對(duì)象哮塞,一旦創(chuàng)建就不能修改
StringBuffer創(chuàng)建之后,可以去修改
StringBuilder也可修改斥铺,執(zhí)行效率高于StringBuffer彻桃,不安全
當(dāng)字符賦值少使用String
字符賦值頻繁使用StringBuilder
當(dāng)多個(gè)線程同步操作數(shù)據(jù),使用StringBuffer
11晾蜘、進(jìn)程和線程的區(qū)別
概念:進(jìn)程包括多個(gè)線程邻眷,一個(gè)程序一個(gè)進(jìn)程,多線程的優(yōu)點(diǎn)可以提高執(zhí)行效率剔交,提高資源利用率
創(chuàng)建:Thread類和Runnable接口肆饶,
常用方法有:
start()用于啟動(dòng)線程
run()調(diào)用線程對(duì)象中的run方法
join()合并插隊(duì)到當(dāng)前線程
sellp()睡眠釋放cpu資源
setPriority()設(shè)置線程優(yōu)先級(jí)
12、隱式Intent與顯示Intent的區(qū)別
顯示intent效率高岖常,系統(tǒng)直接精確定位要啟用的組件驯镊,但耦合度也高,如果通過這種方式調(diào)用一些系統(tǒng)組件的話,容易因?yàn)榘姹靖掳寤螅惷暇怠Y(jié)構(gòu)變化等原因?qū)е鲁绦虮罎⒎氤恕k[式意圖能夠降低程序的耦合度洽胶,但由于每次意圖執(zhí)行的時(shí)候,系統(tǒng)都會(huì)搜索所有可用的intentfilter裆馒,來查看是否有匹配的內(nèi)容姊氓,所以效率更低。