- 1.List<T>和List<?>的區(qū)別切揭?
List<T>是泛型,List<?>是泛型類型通配符锁摔,相當(dāng)于List<? Extends Object>廓旬,他只能取元素不可以放元素。
List< ? super Long> 他可以放元素但是不支持取元素谐腰。
<? Extends superclass> 上邊界限定通配符 "讀"操作使用
<? Super SubClass> 下邊界限定通配符 "寫(xiě)"操作使用
<?> 無(wú)限定通配符 只讀孕豹,不能進(jìn)行增加修改
- 2.泛型的種類?
泛型類十气,泛型接口励背,泛型方法
- 3.使用泛型的原因?
使用泛型和通配符提高了代碼的復(fù)用性砸西。
- 4.app啟動(dòng)慢叶眉,使用卡頓的原因?
1)界面繪制問(wèn)題:層級(jí)太深芹枷,頁(yè)面復(fù)雜衅疙,刷新不合理
2)數(shù)據(jù)處理:數(shù)據(jù)處理量過(guò)大,或者數(shù)據(jù)處理放在了ui線程鸳慈。內(nèi)存增加饱溢,gc頻繁,引起卡頓走芋。
- 5.Throwable绩郎、Exception? 區(qū)別潘鲫?
Throwable是所有異常的基類,它包括Error錯(cuò)誤和Exception異常肋杖。
- 6.異常情況下的activity生命周期溉仑?
點(diǎn)擊home鍵后:onPause - onSaveInstanceState - onStop
重新打開(kāi)手機(jī):onStart - onRestoreInstanceState(actiivy已經(jīng)被銷(xiāo)毀) - onResume
整個(gè)異常生命周期流程:
onCreate() -onStart() - onRestoreInstanceState() - onResume() - onPause()-onSaveInstanceState()-onStop()-onDestroy()
- 7.onSaveInstanceState()和onRestoreInstanceState()在什么時(shí)候被調(diào)用?
onSaveInstanceState
1)關(guān)閉屏幕時(shí) 2)在后臺(tái)內(nèi)存不足時(shí) 3)按下home鍵
onRestoreInstanceState
1)橫豎屏切換 2)當(dāng)前Activity處于后臺(tái),系統(tǒng)資源緊張將其殺死,用戶又啟動(dòng)該Activity
- 8.怎么判斷fragment是否可見(jiàn)兽愤?
- 9.沉浸式狀態(tài)欄
顏色:
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
Window window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0xff01c7d4);
圖片:
- 10.自定義組件常用的方法彼念?
重載onMeasure(),onLayout(),onDraw()三個(gè)函數(shù)構(gòu)建了自定義View的外觀形象。再加上onTouchEvent()等重載視圖的行為垃瞧,
可以構(gòu)建任何我們需要的可感知到的自定義View芥备。
1)View本身大小多少,這由onMeasure()決定
2)View在ViewGroup中的位置如何,這由onLayout()決定
3)繪制View,onDraw()定義了如何繪制這個(gè)View。
- 11.怎么設(shè)置自定義組件的寬高徘郭?
在onMeasure()方法中使用setMeasuredDimension(100, 100)方法來(lái)設(shè)置組件的寬高。
- 12.自定義組件的方法執(zhí)行流程順序丧肴?
onMeasure()繪制大小 (他會(huì)不停的被多次調(diào)用 )
onSizeChanged()組件大小是否改變
onLayout() 自身位置
onMeasure()繪制大小(又會(huì)執(zhí)行多次)
onDraw() 繪制自身 (只有當(dāng)組件大小大于0的時(shí)候才走)
- 13.px和dp之間的大概關(guān)系残揉?
dp = px/2 ;
- 14.自定義組件刷新界面的方式?
invalidate()方法芋浮,用在主線程中刷新抱环。
postInvalidate() 方法,可直接使用在工作線程中纸巷。
- 15.onTouchEvent()方法的返回值意義镇草?
返回false時(shí),就是不處理該事件瘤旨,傳遞給上層組件梯啤。
返回true時(shí),就是該組件要消費(fèi)掉該點(diǎn)擊事件存哲。
返回super.onTouchEvent(event)時(shí)因宇,等于返回false。
- 16.Activity的生命周期?
onCreate() - onStart() [可見(jiàn)不可交互] - onRestoreInstanceState()[異常銷(xiāo)毀時(shí)走] - onResume()[可交互] - onSaveInstanceState()[異常銷(xiāo)毀和橫豎屏切換] - onPause()[可見(jiàn)不可交互] - onStop()[不可見(jiàn)]- onDestory() [銷(xiāo)毀]
- 17.橫豎屏切換的生命周期?
1)不設(shè)置activity的configChanges時(shí)祟偷,切橫屏生命周期一次羽嫡,切豎屏執(zhí)行兩次。
2)設(shè)置configChanges = "orientation"時(shí)肩袍,橫豎屏執(zhí)行一次生命周期
3)設(shè)置configChanges=”orientaion|keyboardHidden”時(shí),生命周期不執(zhí)行婚惫,只會(huì)執(zhí)行onConfigurationChange方法氛赐。*但是個(gè)人建議魂爪,沒(méi)必要設(shè)置這些,所有的重要數(shù)據(jù)都進(jìn)行在onSaveInstanceState()方法中進(jìn)行保存艰管,防止對(duì)象被回收滓侍,導(dǎo)致的crash問(wèn)題。
- 18.activity的啟動(dòng)模式牲芋?和使用場(chǎng)景撩笆?
使用launchMode來(lái)控制啟動(dòng)模式和任務(wù)棧,任務(wù)棧是后進(jìn)先出的結(jié)構(gòu)缸浦。
1)standard:標(biāo)準(zhǔn)模式夕冲,每次都會(huì)在任務(wù)棧新建實(shí)例對(duì)象。onCreate(),onStart(),onResume()方法都會(huì)從新執(zhí)行裂逐。ApplicationContext無(wú)法啟動(dòng)該模式的Activity歹鱼。
2)singleTop:棧頂復(fù)用,實(shí)例在棧頂?shù)脑挷犯撸粍?chuàng)建新實(shí)例弥姻。不執(zhí)行onCreate()方法。但是系統(tǒng)會(huì)調(diào)用onNewIntent()方法掺涛。
3)singleTask:棧內(nèi)復(fù)用庭敦,系統(tǒng)會(huì)先確認(rèn)它所需的任務(wù)棧是否存在,否則先創(chuàng)建任務(wù)棧薪缆,然后放入實(shí)例對(duì)象秧廉。如果該棧存在,會(huì)將該實(shí)例之上的實(shí)例擠出棧矮燎,自己到棧頂定血。會(huì)調(diào)用onNewIntent()方法。
4)singleInstance:單實(shí)例模式诞外,獨(dú)開(kāi)一個(gè)新棧澜沟,在創(chuàng)建一個(gè)新實(shí)例。之后不在創(chuàng)建新實(shí)例峡谊。在onStart()之前調(diào)用onNewIntent()方法茫虽。
使用場(chǎng)景:
1)singleTask:
- 19.怎么加速啟動(dòng)Activity?
onCreate()方法中部要進(jìn)行同步耗時(shí)操作既们。A啟動(dòng)B時(shí)濒析,不要再A中的onPause()方法中執(zhí)行耗時(shí)操作,因?yàn)锽的onResume()方法必須等到A的onPause()執(zhí)行完才會(huì)執(zhí)行啥纸。
- 20.怎么解決Activity之間切換的卡頓問(wèn)題号杏? (App卡頓問(wèn)題)
首先先定位卡頓的原因,根據(jù)原因進(jìn)行處理斯棒。如下:
1)使用BlockCanary開(kāi)源項(xiàng)目處理
2)兩個(gè)activity都使用了一個(gè)同步鎖對(duì)象盾致,導(dǎo)致卡頓主经。優(yōu)化鎖。
3)布局的層級(jí)太深庭惜,導(dǎo)致渲染界面慢罩驻,通過(guò)traceView工具布局分析
4)組件過(guò)多的話,可以使用html5開(kāi)發(fā)
- 21.Activity的緩存方式护赊?
可以在onSaveInstanceState中將要保存的數(shù)據(jù)保存起來(lái)惠遏,可以通過(guò)Bundle進(jìn)行臨時(shí)保存,然后在onCreate中的Bundle中取出來(lái)進(jìn)行恢復(fù)骏啰,這樣就可以避免Activity被銷(xiāo)毀的時(shí)候數(shù)據(jù)的清空节吮。因?yàn)閛nSaveInstanceState在Activity銷(xiāo)毀之前必然會(huì)調(diào)用,所以可以在這里做緩存操作器一。記住课锌,這個(gè)是系統(tǒng)未經(jīng)你同意的時(shí)候就銷(xiāo)毀的時(shí)候才會(huì)的。
- 22 . Service的啟動(dòng)方式和區(qū)別祈秕?不同啟動(dòng)方式的使用場(chǎng)景渺贤?
根據(jù)啟動(dòng)方式有兩種,通過(guò)startService()和bindService请毛。
根據(jù)服務(wù)類型:本地服務(wù)和遠(yuǎn)程服務(wù)
生命周期:
startService(): onCreate() - onStartCommand() - onDestroy()
bindService(): onCreate() - onBind() - onUnbind() - onDestroy()
關(guān)聯(lián):
startService():方法啟動(dòng)的服務(wù)志鞍,調(diào)用者與服務(wù)之間沒(méi)有關(guān)聯(lián),及時(shí)調(diào)用者被銷(xiāo)毀了方仿,服務(wù)仍然會(huì)運(yùn)行固棚,直到使用stopService()/stopSelf()方法停止服務(wù)。
bindService(): 啟動(dòng)服務(wù)后仙蚜,Service是一個(gè)Clicent/Server結(jié)構(gòu)此洲,調(diào)用者可以和Service進(jìn)行交互。調(diào)用者和服務(wù)的生命周期綁定在一起委粉,調(diào)用者一旦退出呜师,服務(wù)也將終止。在onDestory()方法中使用unbindService()方法解除服務(wù)的綁定贾节。
多次啟動(dòng):
startService():多次調(diào)用只執(zhí)行一次onCreate()汁汗,會(huì)多次調(diào)用onStartCommand()方法
bindService():多次調(diào)用不會(huì)多次調(diào)用onCreate()和onBind()方法
- 23.bindService的使用方法?
BindService用于綁定一個(gè)服務(wù)栗涂,這樣當(dāng)bindService(intent,conn,flags)后知牌,就會(huì)綁定一個(gè)服務(wù)。這樣做可以獲得這個(gè)服務(wù)對(duì)象的本身斤程,而startService(intent)只是啟動(dòng)服務(wù)角寸。
第一步:繼承Service,創(chuàng)建內(nèi)部類MyBinder繼承Binder。在內(nèi)部類中創(chuàng)建一個(gè)返回該服務(wù)對(duì)象的實(shí)例方法袭厂。
第二步:重寫(xiě)onBind()方法墨吓,返回MyBinder實(shí)例。
第三步:調(diào)用者中實(shí)例化ServiceConnection接口的實(shí)現(xiàn)類纹磺。重寫(xiě)其中方法。
- 24.onStartCommand()方法的返回值都有哪些和區(qū)別亮曹?
1)start_no_sticky:若執(zhí)行完onStartCommand方法后橄杨,系統(tǒng)銷(xiāo)毀了該服務(wù),不再重新創(chuàng)建服務(wù)照卦。
2)start_sticky:若執(zhí)行完onStartCommand方法后式矫,系統(tǒng)銷(xiāo)毀了該服務(wù),那么Service會(huì)被重新創(chuàng)建并回掉onStartCommand()方法役耕。(該模式適合播放音樂(lè))
3)start_redeliver_intent:若執(zhí)行完onStartCommand方法后采转,系統(tǒng)銷(xiāo)毀了該服務(wù),那么Service會(huì)被重新創(chuàng)建瞬痘,回調(diào)onStartCommand方法故慈,并將組后一個(gè)Intent回傳到該方法。(該模式適合做文件下載的操作)框全。
- 25.怎么在android啟動(dòng)一個(gè)新進(jìn)程察绷?對(duì)其了解?
通過(guò)給四大組件指定androd:process屬性津辩,我們可以輕易的開(kāi)啟多進(jìn)程模式拆撼。
android:process:”:romote”和android:”com.xx.xx”區(qū)別是,以“:”開(kāi)頭的為當(dāng)前應(yīng)用的私有進(jìn)程喘沿,其他應(yīng)用組件不可以進(jìn)入該進(jìn)程闸度。而不以“:”開(kāi)頭的為全局進(jìn)程,其他應(yīng)用可以進(jìn)入該進(jìn)程蚜印。
如果沒(méi)有指定process屬性的話莺禁,運(yùn)行在默認(rèn)進(jìn)程中,默認(rèn)進(jìn)程名為包名晒哄。
開(kāi)啟多進(jìn)程以后會(huì)出現(xiàn)各種奇怪的問(wèn)題睁宰。
例如:A將全局靜態(tài)變量a(Manger.class文件下)從1改為2,然后開(kāi)啟B(單獨(dú)進(jìn)程)寝凌,這時(shí)a變量還是1柒傻,并沒(méi)有改完2。
解釋:這是因?yàn)锽運(yùn)行在單獨(dú)的進(jìn)程中较木,android為每個(gè)應(yīng)用分配了不同的虛擬機(jī)红符,不同的虛擬機(jī)在內(nèi)存中分配不同的地址空間。這就導(dǎo)致在不同的虛擬機(jī)中訪問(wèn)同一個(gè)類的對(duì)象會(huì)產(chǎn)生很多副本。在進(jìn)程com.wx和進(jìn)程com.wx:remote中都存在著一個(gè)Manager類预侯,并且兩個(gè)類是互不干涉的致开,在一個(gè)進(jìn)程中修改a的值,只會(huì)影響當(dāng)前進(jìn)程萎馅,對(duì)其他進(jìn)程不會(huì)造成任何影響双戳。
總結(jié):所有運(yùn)行在不同進(jìn)程的四大組件,只要他們之間需要通過(guò)內(nèi)存來(lái)共享數(shù)據(jù)的話糜芳,都是失敗的飒货。
多進(jìn)程造成的問(wèn)題:
1)靜態(tài)成員和單例模式失效
2)線程同步機(jī)制失效
3)sp可可靠性下降
4)Application會(huì)多次創(chuàng)建
每次啟動(dòng)一個(gè)新線程,就會(huì)創(chuàng)建一個(gè)新的虛擬機(jī)和Application
- 26.怎么防止其他應(yīng)用程序啟動(dòng)您的Serivce組件峭竣?
將android:exported屬性設(shè)置為false塘辅。表示不允許其他應(yīng)用啟動(dòng)本應(yīng)用的組件。
- 27.Service和IntentService的區(qū)別皆撩?
Service是運(yùn)行在主線程中的扣墩,如果要處理耗時(shí)操作,需要開(kāi)啟線程扛吞。IntentSerice是繼承Service類呻惕,它為我們創(chuàng)建了線程,我們直接在onHandleIntent()方法中做耗時(shí)操作喻粹,執(zhí)行完成后也無(wú)需手動(dòng)調(diào)用stopSelf()方法蟆融,onHandleIntent()會(huì)自動(dòng)調(diào)用stopSelf()。但是不可以處理多個(gè)請(qǐng)求守呜。
- 28.為什么在Service中創(chuàng)建子線程而不是Activity中呢型酥?
因?yàn)樵贏ctivity中創(chuàng)建子線程的話,線程是獨(dú)立于組件而存在的查乒,一旦Activity實(shí)例被銷(xiāo)毀弥喉,就無(wú)法重新獲取該線程的控制權(quán)。但是在Service中就不一樣了玛迄,所有的Activity都可以和Serice進(jìn)行關(guān)聯(lián)由境,即使Activity被銷(xiāo)毀,只要在從新與Service進(jìn)行連接蓖议,就可繼續(xù)控制該線程虏杰。
- 29.activity和service怎么進(jìn)行交互?
1)Binder機(jī)制 (+接口監(jiān)聽(tīng))
2)AIDL
3)Broadcast
4)EventBus
- 30.Service的混合調(diào)用順序勒虾?
1)通過(guò)startService(intent)開(kāi)啟服務(wù)
2)然后bindService()綁定該服務(wù)纺阔,這樣可以與服務(wù)進(jìn)行通信了
3)調(diào)用服務(wù)功能結(jié)束后,unbindService()解除綁定
4)最后不需要服務(wù)時(shí)修然,stopService()終止服務(wù)
調(diào)用unbindService將不會(huì)停止Service笛钝,而必須調(diào)用stopService 或 Service的 stopSelf來(lái)停止服務(wù)
- 31.怎么保證Service不被殺死质况?
1)通過(guò)priority提示服務(wù)的優(yōu)先級(jí)
2)將onStartCommand()方法返回值設(shè)置成 start_sticky。
3)提升Service所在進(jìn)程的優(yōu)先級(jí)玻靡,使用startForeground()方法變成前臺(tái)服務(wù)结榄。
4)在Service的onDestory方法中重啟Service。(發(fā)送廣播囤捻,廣播接收者重新啟動(dòng)該服務(wù))
5)在Application加android:persisten = “true”,提高優(yōu)先級(jí)臼朗,保護(hù)進(jìn)程
5)監(jiān)聽(tīng)系統(tǒng)廣播
6)變成系統(tǒng)級(jí)應(yīng)用
7)放一個(gè)像素在前臺(tái)
- 32.android進(jìn)程的優(yōu)先級(jí)?
Android中的進(jìn)程是托管的最蕾,當(dāng)系統(tǒng)進(jìn)程空間緊張的時(shí)候依溯,會(huì)依照優(yōu)先級(jí)自動(dòng)進(jìn)行進(jìn)程的回收。Android將進(jìn)程分為5個(gè)等級(jí),它們按優(yōu)先級(jí)順序由高到低依次是:
1)前臺(tái)進(jìn)程
2)可視進(jìn)程
3)服務(wù)進(jìn)程
4)后臺(tái)進(jìn)程
5)空進(jìn)程
當(dāng)service運(yùn)行在低內(nèi)存的環(huán)境時(shí)瘟则,將會(huì)kill掉一些存在的進(jìn)程。因此進(jìn)程的優(yōu)先級(jí)將會(huì)很重要枝秤,可以使用startForeground 將service放到前臺(tái)狀態(tài)醋拧。這樣在低內(nèi)存時(shí)被kill的幾率會(huì)低一些。
- 33.android提高進(jìn)程優(yōu)先級(jí)的方法淀弹?
1)通過(guò)startForeground()設(shè)置
2)注冊(cè)文下丹壕,在application下,添加android:persistent=”true”薇溃。這樣可以將該進(jìn)程設(shè)置為常駐內(nèi)存進(jìn)程菌赖。
- 34.Binder機(jī)制的理解?
Binder是android實(shí)現(xiàn)進(jìn)程間通信(IPC)的方式之一沐序。Binder屬于一個(gè)驅(qū)動(dòng)琉用,工作在Linux層,運(yùn)行在內(nèi)核空間策幼,程序?qū)inder的使用是通過(guò)系統(tǒng)的調(diào)用完成的邑时。
binder架構(gòu)是由服務(wù)器,binder驅(qū)動(dòng)特姐,app客戶端三部分組成晶丘。
服務(wù)器:一個(gè)binder服務(wù)器就是一個(gè)Binder對(duì)象。當(dāng)創(chuàng)建一個(gè)Binder對(duì)象后唐含,內(nèi)部就會(huì)開(kāi)啟一個(gè)線程浅浮,這個(gè)線程用于接收binder驅(qū)動(dòng)發(fā)送的信息,然后執(zhí)行相關(guān)服務(wù)代碼捷枯。
Binder驅(qū)動(dòng):當(dāng)服務(wù)器端成功創(chuàng)建一個(gè)Binder對(duì)象后滚秩,Binder也會(huì)創(chuàng)建個(gè)remote對(duì)象,該對(duì)象也是Binder類铜靶,客戶端通過(guò)這個(gè)remote對(duì)象來(lái)訪問(wèn)遠(yuǎn)程服務(wù)叔遂。
選Binder來(lái)實(shí)現(xiàn)進(jìn)程通信的原因是
1)可靠性(對(duì)比c/s) 2)傳輸性能(對(duì)比socket) 3)安全性(UID/PID)
- 35.ANR是什么他炊?怎么造成的?
Android not responding應(yīng)用程序無(wú)響應(yīng)已艰。Android執(zhí)行時(shí)長(zhǎng)為5s ,廣播為 10s痊末,服務(wù)為20s.
- 36.廣播接收者的注冊(cè)方式有幾種,有什么區(qū)別哩掺?
靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)兩種方式凿叠。
靜態(tài)注冊(cè)是在注冊(cè)文件中進(jìn)行注冊(cè),這種方式注冊(cè)的廣播是常駐型廣播嚼吞,及時(shí)應(yīng)用程序關(guān)閉了盒件,依然可以接受廣播。使用intent-filter進(jìn)行匹配廣播舱禽。
動(dòng)態(tài)注冊(cè)是在代碼中進(jìn)行注冊(cè)炒刁,為非常駐型廣播,跟隨Activity的生命周期誊稚,所以要在onDestory中對(duì)廣播進(jìn)行注銷(xiāo)registerReceiver()翔始。
- 37.廣播有幾種類型?
無(wú)序廣播和有序廣播
無(wú)序廣播:通過(guò)sendBroadcast()里伯,
有序廣播:通過(guò)sendOrderedBroadcast()發(fā)送城瞎,根據(jù)廣播接收者的優(yōu)先級(jí)priority進(jìn)行傳遞,中間可以對(duì)廣播進(jìn)行修改和中斷疾瓮。
- 38.Handler機(jī)制的原理脖镀?
Android提供了Handler和Looper來(lái)滿足線程間的通信。
Handler:是線程間通信的橋梁狼电,運(yùn)行在主線程中蜒灰。通過(guò)它進(jìn)行消息的發(fā)送和接收。
MessageQueue:是消息隊(duì)列漫萄,存放線程發(fā)送來(lái)的消息卷员。
Looper:是消息隊(duì)列的管理者,它會(huì)不停對(duì)進(jìn)行消息隊(duì)列進(jìn)行輪詢腾务,然后分發(fā)消息給Handler毕骡。
工作過(guò)程:
activity在創(chuàng)建的時(shí)候,調(diào)用Looper.PrepareMainLooper()方法岩瘦,來(lái)創(chuàng)建Looper對(duì)象和MessageQueue對(duì)象未巫。當(dāng)在UI線程創(chuàng)建Handler對(duì)象時(shí),此時(shí)Handler與Looper启昧,MessageQueue進(jìn)行關(guān)聯(lián)叙凡。當(dāng)Handler對(duì)象在子線程中sendMessage時(shí),會(huì)將消息放入消息隊(duì)列中密末,Loopr對(duì)象通過(guò)無(wú)限循環(huán)查看的方式對(duì)消息隊(duì)列進(jìn)行管理握爷,當(dāng)有Message時(shí)跛璧,將Message發(fā)布給Handler對(duì)象追城,收到消息的Handler會(huì)調(diào)用HandlerMessage()方法進(jìn)行處理燥撞。
- 39.View的繪制流程?
Measure(測(cè)量) - layout(布局) - draw(繪圖) 這三大流程。分別提供了重寫(xiě)方法割粮。
onMeasure :通過(guò)MeasureSpec可以獲取組件的寬高模式和大小。然后通過(guò)setMeasuredDimension()方法設(shè)置實(shí)際組件的寬高媚污。
onLayout:ViewGroup用來(lái)確定子元素的位置舀瓢,當(dāng)ViewGroup的位置被確定后,它在onLayout中會(huì)遍歷所有的子元素并調(diào)用其layout方法耗美。
onDraw:將view繪制到屏幕上京髓。
- 40.View的事件分發(fā)機(jī)制?
從Activity的dispatchTouchEvent()方法開(kāi)始商架,只要沒(méi)有被攔截就繼續(xù)向下傳遞堰怨。調(diào)用ViewGroup的dispatchTouchEvent()方法中的onIterceptTouchEvent()攔截事件,如果返回ture的話蛇摸,就處理該事件备图,調(diào)用onTouchEvent方法。如果返回false的話赶袄,就會(huì)遍歷它的子View揽涮,判斷是否有接收的,如果有繼續(xù)向下分發(fā)饿肺。如果沒(méi)有就ViewGroup自身處理蒋困。事件分發(fā)到View后,會(huì)調(diào)用dispatchTouchEvent方法敬辣,調(diào)用onTouchEvent方法判斷是否攔截事件雪标,如果攔截就消費(fèi)該事件零院。如果不消費(fèi),就向上傳遞村刨,直到Activity的OnTouchEvent方法告抄。
- 41.invalidate和postInvalidate區(qū)別?
更新View視圖的方式有兩種烹困,invalidate和postInvalidate玄妈。其中前者是在UI線程中使用。
后者可以在子線程中更新視圖髓梅。
- 42.view和SurfaceView的區(qū)別拟蜻?
View:必須在UI線程中更新畫(huà)面,速度較慢枯饿。
SurfaceView:是View的子類酝锅。使用了雙緩沖技術(shù),在新線程中更新畫(huà)面奢方,所有刷新界面速度快搔扁。(雙緩沖就是前后緩存和后臺(tái)緩存,后臺(tái)緩存計(jì)算場(chǎng)景蟋字,產(chǎn)生畫(huà)面稿蹲;前臺(tái)緩存顯示后臺(tái)緩存已畫(huà)好的畫(huà)面)
- 43.android數(shù)據(jù)持久化的方式?
系統(tǒng)提供了三種方式用于數(shù)據(jù)持久化鹊奖。1)文件存儲(chǔ)2)sharedPreference 3 )數(shù)據(jù)庫(kù)
文件存儲(chǔ):Context提供了openFileOutput()方法苛聘,將文件保存到/data/data/<包名>/files/目錄下。openFileOutput(“filename”,Context.MODE_APPEND);
其中參數(shù)2忠聚,有兩種類型:
MODE_PRIVATE——默認(rèn)模式设哗,指定文件名相同時(shí),寫(xiě)入內(nèi)容將覆蓋原有內(nèi)容
MODE_APPEND——追加模式两蟀,如果該文件已存在网梢,則追加內(nèi)容;否則創(chuàng)建文件
- 44.MVC和MVP的區(qū)別赂毯?
Mvc:View層可跟Model層進(jìn)行交互战虏,代碼臃腫,高耦合欢瞪。通信是單向
Mvp: m和v不可交互活烙,通信是雙向。
1)視圖層和業(yè)務(wù)邏輯層進(jìn)行分離遣鼓,降低了耦合啸盏。
2)業(yè)務(wù)邏輯層可重用,一個(gè)p層可用于多個(gè)v
3)把業(yè)務(wù)邏輯放到p層骑祟,避免后臺(tái)線程引用Activity導(dǎo)致資源無(wú)法釋放回懦,發(fā)生內(nèi)存泄漏問(wèn)題气笙。
4)方便進(jìn)行單元測(cè)試
5)View可進(jìn)行組件化,對(duì)外只提供接口怯晕,可高度復(fù)用View潜圃。
- 45.oom是什么?
內(nèi)存泄漏舟茶,對(duì)象可達(dá)但是無(wú)用谭期,無(wú)法被釋放,占用內(nèi)存吧凉。
內(nèi)存的分配策略:
靜態(tài)存儲(chǔ)區(qū):常量
棧區(qū):基本數(shù)據(jù)類型隧出,對(duì)象引用,局部變量
堆區(qū):對(duì)象阀捅,數(shù)組
常見(jiàn)的造成oom的:
1)靜態(tài)集合類
2)監(jiān)聽(tīng)器不注銷(xiāo)
3)數(shù)據(jù)庫(kù)胀瞪,io,網(wǎng)絡(luò)連接等資源未關(guān)閉
4)非靜態(tài)內(nèi)部類引用外部實(shí)例
5)單例模式饲鄙,傳人context
6)Handler+異步
7)大量使用static成員變量
- 46.android的性能優(yōu)化凄诞?
通過(guò)內(nèi)存管理+布局+項(xiàng)目結(jié)構(gòu)
內(nèi)存管理的優(yōu)化:
1)減少對(duì)象的創(chuàng)建
2)使用線程池對(duì)線程進(jìn)行管理
3)修改對(duì)象的引用類型
4)對(duì)圖片加載的優(yōu)化
5)常量使用staic final修飾符
6)合理使用容器,盡量使用優(yōu)化過(guò)的數(shù)據(jù)容器忍级,如:SparseArray
7)當(dāng)界面不可見(jiàn)時(shí)釋放內(nèi)存帆谍,重寫(xiě)onTrimMemory()方法,來(lái)釋放資源轴咱。
8)方法中如果不使用實(shí)例變量既忆,改為靜態(tài)方法。
9)減少不必要的全局變量
10)避免使用枚舉
11)減少同步鎖的區(qū)域范圍
12)增加app的內(nèi)存使用
13)謹(jǐn)慎使用抽象編程嗦玖,會(huì)增加app的內(nèi)存占用
14)在注冊(cè)文件中添加android:largeHeap="true",app內(nèi)存從16M增加到96M
15)使用AndResGuard對(duì)代碼進(jìn)行壓縮和混淆
16)使用LeakCanary進(jìn)行分析
布局優(yōu)化:
1)使用include,viewStub,merge 減少布局層級(jí)
2)使用TraceView對(duì)布局進(jìn)行分析
3)復(fù)雜的界面可以使用h5
項(xiàng)目結(jié)構(gòu):
1)將公用代碼放入androidLib包中
其他:
靜態(tài)檢查+單元測(cè)試
- 47.描述一下android的系統(tǒng)架構(gòu)跃脊?
從下往上分5層:Linux內(nèi)核層(硬件驅(qū)動(dòng))宇挫,系統(tǒng)運(yùn)行層(C/C++),應(yīng)用程序框架層(api)酪术,應(yīng)用程序?qū)?app)器瘪。
- 48.文件存儲(chǔ)和數(shù)據(jù)庫(kù)存儲(chǔ)哪個(gè)效率高?
文件高绘雁。
- 49.Intent可以傳遞哪些數(shù)據(jù)類型橡疼?
基本數(shù)據(jù)類型,數(shù)組庐舟,序列化后的對(duì)象欣除。
- 50.怎么將數(shù)據(jù)庫(kù)(xx.db)和app一起打包發(fā)布?
將數(shù)據(jù)庫(kù)(xx.db)放在res/raw/文件下挪略,raw下的文件不會(huì)打包成二進(jìn)制
- 51.res/raw 和assets的相同點(diǎn)和區(qū)別历帚?
相同點(diǎn):兩個(gè)目錄下的文件在打包后保持原樣在apk包中滔岳,不會(huì)被編譯成二進(jìn)制。
不同點(diǎn):
raw中的文件會(huì)被映射到R.java文件中挽牢,訪問(wèn)的時(shí)候直接使用id谱煤。不可以再有目錄結(jié)構(gòu)。
assets中的文件不會(huì)映射禽拔,通過(guò)AssetManager類刘离。可再建立目錄結(jié)構(gòu)睹栖。
- 52.Service中可以使用Toast嗎硫惕?
可以的,Toast是運(yùn)行在UI線程中的磨淌。Service也是運(yùn)行在Ui線程疲憋。
如果子線程使用Toast,要首先創(chuàng)建Looper。
- 53.ListView的優(yōu)化梁只?
1)復(fù)用convertView缚柳,減少View對(duì)象的創(chuàng)建
2)自定義靜態(tài)ViewHolder,減少findViewById的次數(shù)
3)異步加載數(shù)據(jù)
4)分頁(yè)加載
- 54.PostDelayed(run,2000)會(huì)造成線程阻塞嗎搪锣?對(duì)內(nèi)存有什么影響秋忙?
不會(huì)阻塞主線程
- 55.異步更新UI的方式?
1)handler.sendMessage()
2)handler.post(Runnable r)
3)使用Activity對(duì)象的runOnUiThread方法
4)使用View.post(Runnable r);
5)AsyncTask異步任務(wù)
- 56.android5.0的新特性构舟?
1)全新的Material Design 設(shè)計(jì)風(fēng)格
2)支持多種設(shè)備
3)全新風(fēng)格的通知系統(tǒng)
4)支持64位ART虛擬機(jī)(放棄了Dalvik虛擬機(jī))
5)電池續(xù)航改進(jìn)計(jì)劃(可以清除的知道電量使用)
6)改進(jìn)安全性
7)藍(lán)牙4.1
8)控件方面:
*動(dòng)態(tài)切換主題
*設(shè)置View的高度和陰影
*Palette的使用
*水波紋動(dòng)畫(huà)
*CardView 卡片
*RecyclerView的使用
*ToolBar :代替了ActionBar
- 57.android6.0的新特性灰追?
1)權(quán)限方面:增加運(yùn)行時(shí)permissions(權(quán)限),之前是安裝時(shí)會(huì)讓用戶同意各種權(quán)限」烦現(xiàn)在是在用的時(shí)候弹澎,在去詢問(wèn)。
2)電源管理:增加三種省電模式(Doze和App standby努咐,Exemptions)
3)存儲(chǔ)方面:可將sd卡進(jìn)行加密作為內(nèi)置存儲(chǔ)苦蒿。
4)主題方面:系統(tǒng)主題 亮/暗色切換
3)控件方面:
*TextInputLayout :炫酷的輸入框
*FloatingActionButton:懸浮按鈕
*SnackBar:類似Toast的提示控件
*TabLayout:跟ViewPager結(jié)合使用
*CoordinatorLayout:協(xié)調(diào)布局
- 58.android7.0的新特性?
1)多窗口的支持
2)通知增強(qiáng)功能
3)快速安裝應(yīng)用
4)隨時(shí)隨地低電耗模式
5)屏蔽來(lái)電號(hào)碼
6)VR的支持
- 59.android序列化的方式渗稍?
Parcelable和Serializable佩迟。Serializable是java的,Parcelable是android的竿屹。
Serializable在序列化的時(shí)候會(huì)產(chǎn)生大量的臨時(shí)變量报强,從而引起頻繁的GC,而相比之下Parcelable的性能更高
- 60.NDK是什么拱燃?
NDK是一系列工具集合秉溉,幫助開(kāi)發(fā)者快速開(kāi)發(fā)c/c++的動(dòng)態(tài)庫(kù)。
NDK性能高,保密安全坚嗜。
- 61.Volley夯膀,F(xiàn)resco乃秀,Glide和Picasso的區(qū)別和優(yōu)缺點(diǎn)弦疮?
Volley(谷歌公司):特別適合數(shù)據(jù)量小,通信頻繁的網(wǎng)絡(luò)操作仅颇。volley 不適合請(qǐng)求較大的數(shù)據(jù)碟绑,比如下載文件俺猿,下載大圖片等。
Fresco(faceBook公司):使用三級(jí)緩存格仲,圖片占用內(nèi)存可及時(shí)釋放押袍。適合多圖片。包太大
Picasso(square公司):圖片質(zhì)量高
Glide:和Picasso差不多凯肋,加載速度快谊惭,加載緩存效率高,但是Gif是殺手锏
- 62.常見(jiàn)的網(wǎng)絡(luò)通信開(kāi)源框架侮东?
1)Volley(谷歌公司):網(wǎng)絡(luò)請(qǐng)求排序圈盔,請(qǐng)求優(yōu)先級(jí)處理,緩存悄雅,可取消請(qǐng)求驱敲,和Acitiyt的生命周期聯(lián)動(dòng),activity結(jié)束時(shí)同時(shí)取消所有網(wǎng)絡(luò)請(qǐng)求宽闲。
2)android-async-http:支持?jǐn)帱c(diǎn)續(xù)傳众眨,默認(rèn)gZip壓縮,
3)retrofit:
4)Okttp:
- 63.多進(jìn)程的理解容诬?
在android中一個(gè)進(jìn)程就是一個(gè)jvm娩梨。
使用多進(jìn)程的好處:
1)分擔(dān)主進(jìn)程的壓力,可用于做非讀寫(xiě)數(shù)據(jù)外的其他耗時(shí)操作览徒。比如開(kāi)機(jī)啟動(dòng)這個(gè)進(jìn)程姚建。
2)守護(hù)進(jìn)程,可以和主進(jìn)程相互監(jiān)視吱殉,有一方被殺死就重新啟動(dòng)對(duì)方。
缺點(diǎn):
1)耗點(diǎn)厘托,占用系統(tǒng)內(nèi)存空間友雳。新進(jìn)程的創(chuàng)建會(huì)影響Application的實(shí)例,onCreate()會(huì)在執(zhí)行一次铅匹。
2)不同進(jìn)程之間內(nèi)存不能共享押赊,單例模式,sp等都會(huì)失效。
3)通信麻煩流礁,使用AIDL涕俗。
- 64 . 通信加密的使用?
Base64:使用A-Z,a-z,0-9,+,/ 這64個(gè)字符神帅,嚴(yán)格意義上說(shuō)再姑,base64不是加密算法,而是一種編碼和解碼算法找御。編碼原理就是將3個(gè)字節(jié)轉(zhuǎn)為4個(gè)字節(jié)元镀。
MD5:用于密碼的加密工作。MD5加密是不可逆向的霎桅,將字符轉(zhuǎn)為大串整數(shù)栖疑。 AES(DES)是對(duì)稱加密,但是DES非常古老了滔驶,已經(jīng)可以被破解遇革。AES是在DES的基礎(chǔ)上,進(jìn)行了增強(qiáng)揭糕。高效萝快,但是存在密鑰交換問(wèn)題。
DH:為了解決對(duì)稱加密的密鑰交換問(wèn)題插佛,而產(chǎn)生杠巡。兩端各有公鑰和私鑰,相互交換公鑰后雇寇,在通過(guò)公鑰和私鑰生產(chǎn)本地私鑰氢拥,進(jìn)行加解密工作。高效
RSA:是非對(duì)稱加密锨侯,公鑰和私鑰不同嫩海。通常用于數(shù)據(jù)加密和數(shù)字簽名。效率低
- 65.Activity的創(chuàng)建過(guò)程囚痴?
1)在activityThread中創(chuàng)建Activity的對(duì)象叁怪,Activity是控制生命周期和處理事件,但是不控制視圖深滚。
2)調(diào)用handleResumeActivity方法將Activity的頂層視圖DecorView添加到窗口視圖window上奕谭。
3)創(chuàng)建ViewRoot對(duì)象,將頂層視圖和窗口視圖進(jìn)行關(guān)聯(lián)痴荐。
4)ViewRoot通過(guò)performMeasue開(kāi)始繪制組件血柳。
- 66.OkHttp的原理?
1)高效的使用http生兆,使用okio庫(kù)代替了java.io包难捌,更快的處理數(shù)據(jù)。
2)支持http1.0/1.1,http2.0根吁,SPDY協(xié)議
3)使用DiskLruCache內(nèi)置緩存员淫,默認(rèn)是不使用的
4)要使用緩存返回體要包含“cahce-control”,如果沒(méi)有,就要通過(guò)攔截器進(jìn)行處理
5)使用門(mén)面模式進(jìn)行設(shè)計(jì)
6)Oktttp內(nèi)有線程池击敌,Volley沒(méi)有線程池
7)更快更省流量介返,SDPY和GZIP的支持。
8)Square出品
- 67.Picasso和Glide的區(qū)別愚争?
Picasso是square公司出品映皆。
Glide是google出品,基于picasso進(jìn)行的二次開(kāi)發(fā)轰枝,所以進(jìn)行了優(yōu)化和改進(jìn)捅彻,但是比picasso大了400k,支持GIF動(dòng)態(tài)圖鞍陨。
- 68.守護(hù)線程的理解步淹?
守護(hù)線程,是指在程序運(yùn)行期間在后臺(tái)提供的一種通用服務(wù)線程诚撵,比如垃圾回收線程就是一個(gè)守護(hù)線程缭裆。通過(guò)調(diào)用Thread對(duì)象的setDaemon(true)方法來(lái)將線程轉(zhuǎn)換為守護(hù)線程。
- 69.android的動(dòng)畫(huà)有幾種寿烟?
三種澈驼,幀動(dòng)畫(huà),補(bǔ)間動(dòng)畫(huà)和屬性動(dòng)畫(huà)筛武。
- 70.避免在類的內(nèi)部進(jìn)行Getters/Setters原因缝其?
公共的類定義getters、setters會(huì)調(diào)用虛擬機(jī)徘六。在類中最好通過(guò)局部變量的方式來(lái)訪問(wèn)内边。
如:
for (int i = 0; i < this.getCount();i++)
dumpItem(mItems[i]);
應(yīng)該寫(xiě)為:
int mCount = this.getCount();
for (int i = 0; i < mCount; i++)
dumpItems(items[i]);
- 71 . 為什么盡量使用內(nèi)部類?
如果該類僅僅在某個(gè)調(diào)用者使用待锈,那么把它設(shè)計(jì)成調(diào)用者的內(nèi)部類漠其。具體的例子,參見(jiàn):com.zte.resmaster.system.rescomp.dao.RescompDAOOracle竿音。不會(huì)暴露該內(nèi)部類和屎,避免濫用而導(dǎo)致的維護(hù)問(wèn)題。
- 72.使用弱引用WeakReference代替強(qiáng)引用的場(chǎng)景春瞬?
使用弱引用代替強(qiáng)引用柴信,弱引用可以讓你保持對(duì)對(duì)象的引用,同時(shí)允許gc在必要時(shí)釋放該對(duì)象快鱼。
- 73 . launchMode啟動(dòng)模式的設(shè)置規(guī)則?
主頁(yè)面設(shè)置為singleTask,一般界面設(shè)置為singleTop抹竹。
- 74 . 怎么保證應(yīng)用在后臺(tái)不被殺死线罕?
早起使用Service處理,但是會(huì)有中斷和被殺死情況窃判。
使用WakeLock保持app在后臺(tái)不被殺死钞楼。PowerManager負(fù)責(zé)對(duì)Android設(shè)備電源相關(guān)進(jìn)行管理,而系統(tǒng)通過(guò)各種鎖對(duì)電源進(jìn)行控制袄琳,WakeLock是一種鎖機(jī)制询件,只要有人拿著這把鎖,系統(tǒng)就無(wú)法進(jìn)入休眠階段唆樊。
WakeLock wakeLock = null;
//獲取電源鎖宛琅,保持該服務(wù)在屏幕熄滅時(shí)仍然獲取CPU時(shí),保持運(yùn)行
private void acquireWakeLock(){
if (null == wakeLock) {
PowerManager pm = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "PostLocationService");
if (null != wakeLock) {
wakeLock.acquire();
}
}
}
//釋放設(shè)備電源鎖
private void releaseWakeLock() {
if (null != wakeLock){
wakeLock.release();
wakeLock = null;
}
}
- 75 . 6.0以后sd卡文件的讀寫(xiě)權(quán)限處理逗旁?
不僅要在注冊(cè)文件下進(jìn)行權(quán)限注冊(cè)嘿辟,同時(shí)還要在代碼中進(jìn)行請(qǐng)求權(quán)限的處理。否則會(huì)報(bào) ErrnoException: open failed: EACCES (Permission denied) 異常片效。
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE);
}
}
- 76 . 使用tv.getLayoutParams()方法的小技巧红伦?
ViewGroup.LayoutParams params = imageview.getLayoutParams();
if(params != null){ //此處一定要判空,如果組件沒(méi)有父控件淀衣,返回為null
params.height = 100;
params.width = 100;
imageview.setLayoutParams(params);
}
- 77 . 怎么獲取一張圖片的保存時(shí)間昙读?
一張圖片是一張路徑,將路徑轉(zhuǎn)換為File對(duì)象膨桥,然后調(diào)用File對(duì)象的lastModified()方法蛮浑。就可以獲取一個(gè)long類型的返回值。
- 78 .map的使用總結(jié)国撵?
之前map的使用陵吸,一直都是用來(lái)背的。從沒(méi)有真正的去理解介牙。死記硬背又很快的忘記壮虫。正好今天做了一個(gè)微信圖片展示的功能,里面涉及到了map的使用』反。現(xiàn)在進(jìn)行總結(jié)下:
map是鍵值對(duì)集合接口囚似。實(shí)現(xiàn)類 包括:HashMap,TreeMap,Hashtable,LinkedHashMap。
平時(shí)的開(kāi)發(fā)中线得,我都是一直使用的HashMap饶唤,可能是因?yàn)楹闷磳?xiě)吧。但是HashMap的使用場(chǎng)景是無(wú)序的情況下贯钩。所以想要對(duì)map中數(shù)據(jù)進(jìn)行排序的話可以使用TreeMap,它是基于紅黑樹(shù)實(shí)現(xiàn)募狂,映射是根據(jù)鍵的自然順序進(jìn)行排序的办素。
Map<String, String> map = new TreeMap<String, String>(
new Comparator<String>() {
public int compare(String obj1, String obj2) {
// 降序排序
return obj2.compareTo(obj1);
}
});
map.put("b", "ccccc");
map.put("d", "aaaaa");
map.put("c", "bbbbb");
map.put("a", "ddddd");
Set<String> keySet = map.keySet();
Iterator<String> iter = keySet.iterator();
while (iter.hasNext()) {
String key = iter.next();
System.out.println(key + ":" + map.get(key));
}
}
- 79 .加大app緩存空間的方法?
在Manifest文件Application加android:largeHeap="true"屬性
- 80 .軟引用和弱引用的區(qū)別?
軟引用用于高速緩存祸穷。每一個(gè)對(duì)象通過(guò)軟引用進(jìn)行實(shí)例化性穿,那么這個(gè)對(duì)象的數(shù)據(jù)也就會(huì)被保存起來(lái),當(dāng)需要再次調(diào)用這個(gè)對(duì)象中的數(shù)據(jù)的時(shí)候雷滚,只需要通過(guò)對(duì)象的get()方法就可以獲取到該對(duì)象所保存的數(shù)據(jù)信息
//創(chuàng)建對(duì)象
Object obj = new Object();
//將對(duì)象放入緩存中
SoftReference sc = new SoftReference(obj);
if(sc != null){
obj = sc.get();
}
項(xiàng)目使用場(chǎng)景:Bitmap圖片處理
在讀取圖片時(shí)需曾,對(duì)于像素很高的圖片
非常的消耗內(nèi)存,andoid堆大小是16M祈远。如果讀取的圖片太多呆万,導(dǎo)致omm。因此使用軟引用來(lái)保存Bitmap對(duì)象车份。流程如下:讀取一張圖片谋减,這張圖片被讀取后就以cache的形式保存起來(lái),當(dāng)使用時(shí)躬充,直接通過(guò)軟引用的get()方法獲取逃顶。這樣就避免多次讀取,直接從cahce中獲取就可以了充甚。當(dāng)內(nèi)存將要發(fā)生oom時(shí)以政,GC會(huì)將軟引用對(duì)象釋放。
public class TestActivity {
private Map<String,SoftReference<Bitmap>> cache = new HashMap<>();
public Bitmap get(String url){
if(cache.containsKey(url)){
return null;
}
return cache.get(url).get();
}
public void put(String url,Bitmap bitmap){
cache.put(url,new SoftReference<Bitmap>(bitmap));
}
}
弱引用的話伴找,在android的部分盈蛮,一般是結(jié)合handler一起使用,來(lái)避免handler導(dǎo)致的內(nèi)存泄漏技矮。
- 81 . 常見(jiàn)的oom抖誉?
對(duì)象不及時(shí)釋放,static使用衰倦,線程不可控袒炉,讀取Bitmap。
- 82 . ReferenceQueue引用隊(duì)列是什么樊零?
- 83 . Handler 造成內(nèi)存泄漏的原因和解決辦法我磁?
只要是handler聲明成static就不會(huì)造成內(nèi)存泄漏,聲明成弱引用activity的話驻襟,雖然也不會(huì)造成內(nèi)存泄漏夺艰,但是需要等到handler中沒(méi)有執(zhí)行的任務(wù)后才會(huì)回收,因此性能不高沉衣。
handler之所以造成內(nèi)存泄漏是因?yàn)樵赼ctivity銷(xiāo)毀的時(shí)候郁副,handler中有未執(zhí)行完的任務(wù)。那么接下來(lái)我們?cè)贏ctivity銷(xiāo)毀的時(shí)候清空handelr沒(méi)有執(zhí)行的任務(wù)會(huì)是什么效果豌习?(現(xiàn)也沒(méi)有內(nèi)存泄漏)
protected void onDestroy() {
super.onDestroy();
//清空所有handler中沒(méi)有執(zhí)行完的任務(wù)
handler.removeCallbacksAndMessages(null);
}
總結(jié):
- handler 造成內(nèi)存泄漏的原因在Activity銷(xiāo)毀時(shí)還有未完成的任務(wù)
- 靜態(tài)static Handler 可以解決內(nèi)存泄漏問(wèn)題
- 只使用弱引用存谎,不使用靜態(tài)也可以解決內(nèi)存泄漏問(wèn)題拔疚,但是要等handler中的任務(wù)全部執(zhí)行完,才會(huì)釋放activity
- 兩種方案:1)activity銷(xiāo)毀時(shí)既荚,移除handler中所有任務(wù)草雕。2)靜態(tài)Handler + 弱引用(不要單獨(dú)使用弱引用性能不高)
- 84 . LRU算法是什么?
最近最少使用算法固以,根據(jù)數(shù)據(jù)的歷史訪問(wèn)記錄來(lái)進(jìn)行淘汰數(shù)據(jù)。
新數(shù)據(jù)放入表頭嘱巾,表滿時(shí)憨琳,將表尾數(shù)據(jù)丟棄。
- 85 . LruCache類的介紹旬昭?
LruCache是android提供的一個(gè)緩存工具類篙螟,其算法是最近最少使用算法。它把最近使用的對(duì)象用“強(qiáng)引用”存儲(chǔ)在LinkedHashMap中问拘,并且把最近最少使用的對(duì)象在緩存值達(dá)到預(yù)設(shè)定值之前就從內(nèi)存中移除遍略。
- 86 . 寫(xiě)一個(gè)方法最重要的注意事項(xiàng)?(編碼能力)
1.傳入?yún)?shù)是否進(jìn)行判斷在使用
2.try catch 進(jìn)行處理
3.對(duì)其他方法返回的參數(shù)骤坐,進(jìn)行判空處理后再使用
4.復(fù)雜的工作要開(kāi)線程處理
- 87 . 編寫(xiě)將d盤(pán)下所有mp3格式的文件地址輸出绪杏?
public class Demo {
//獲取D盤(pán)里所有后綴為.krc文件
private List<String> list = new ArrayList<>();
public static void main(String[] str){
/**
* 1.傳入?yún)?shù)是否進(jìn)行判斷在使用
* 2.try catch 進(jìn)行處理
* 3.對(duì)其他方法返回的參數(shù),進(jìn)行判空處理后再使用
*/
new Thread(new Runnable() {
@Override
public void run() {
Demo de = new Demo();
List<String> list = de.scanDFile(new File("d:\\\\"));
System.out.print(list.toString());
}
}).start();
}
private List<String> scanDFile(File file){
if(file == null ||!file.exists()) return null;
try {
File[] files = file.listFiles(); //獲取該文件下所有文件
if(files == null) return null;
for (File item:files) {
if(item.isDirectory()){
scanDFile(item);
}else {
if(item.getName().endsWith(".krc")){
list.add(item.getAbsolutePath());
}
}
}
return list;
}catch (Exception ex){
System.out.print("錯(cuò)誤");
ex.printStackTrace();
}
return null;
}
}
- 88 . 單例模式編寫(xiě)纽绍?
public class Demo {
private static Demo demo = null;
private Demo(){}
//雙重鎖 解決兩個(gè)線程同時(shí)到達(dá)蕾久,同時(shí)調(diào)用 getInstance()
public static Demo getInstance(){
if(demo ==null){
synchronized (Demo.class){
if(demo == null){
demo = new Demo();
}
}
}
return demo;
}
}
- 89 . Rxandroid的使用原理?
設(shè)計(jì)模式使用到了:觀察者模式和建造者模式拌夏。是一種響應(yīng)式開(kāi)發(fā)模式僧著。
public void rxandroid(){
//被觀察者Observable
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
if(!subscriber.isUnsubscribed()){ //是否訂閱
subscriber.onNext("XXXXXXXXXXXX");
subscriber.onCompleted();
}
}
}).subscribeOn(Schedulers.io()) //被觀察者在工作線程
//觀察者observe
.observeOn(AndroidSchedulers.mainThread()) //觀察者在主線程
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
}
});
}
//Rxandroid+okHttp的結(jié)合
public void rxandroid2Http() {
Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(final Subscriber<? super Bitmap> subscriber) {
if (!subscriber.isUnsubscribed()) { //是否訂閱
Request request = new Request.Builder().url(PATH).build();
new OkHttpClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
subscriber.onError(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
byte[] data = response.body().bytes();
if (data != null) {
subscriber.onNext(BitmapFactory.decodeByteArray(data, 0, data.length));
}
subscriber.onCompleted();
}
}
});
}
}
}).subscribeOn(Schedulers.io()) //被觀察者在工作線程
//觀察者observe
.observeOn(AndroidSchedulers.mainThread()) //觀察者在主線程
.subscribe(new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Bitmap s) {
}
});
}
- 90 . 數(shù)組初始化方式有幾種?
靜態(tài)初始化和動(dòng)態(tài)初始化障簿。
- 91 . 當(dāng)一個(gè)View的大小或者位置發(fā)生改變時(shí)盹愚,繪制的流程?
任何時(shí)候View中的繪制內(nèi)容發(fā)生變化時(shí)站故,都需要重新創(chuàng)建DisplayList皆怕,渲染DisplayList,更新到屏幕等操作世蔗。當(dāng)一個(gè)Button的大小變?yōu)樵瓉?lái)的兩倍時(shí)端逼,在增大Button之前,需通過(guò)父View重新計(jì)算并擺放其子View的位置污淋。修改View的大小或者位置會(huì)觸發(fā)整個(gè)HierarcyView的重新計(jì)算大小操作顶滩。
- 92 . 優(yōu)化布局的方式?
使用include來(lái)復(fù)用布局寸爆,使用merge來(lái)減少層級(jí)礁鲁,使用viewStub來(lái)進(jìn)行延遲加載組件盐欺。
merge一般是結(jié)合include來(lái)使用的,他會(huì)直接使用父組件的屬性仅醇,如果父組件是LinearLayout那么使用merge時(shí)冗美,他就是LinearLayout了。
- 93 . 如何避免過(guò)度繪制析二?
1)通過(guò)Hierarchy view來(lái)查看層級(jí)情況粉洼,減少層級(jí)。去掉非必須背景叶摄,去掉非必需組件屬性属韧。activity會(huì)設(shè)置一個(gè)默認(rèn)背景,這個(gè)背景DecorView背景對(duì)我們來(lái)說(shuō)是無(wú)用的蛤吓,但是它會(huì)被渲染一次宵喂,可以通過(guò)this.getwindow().setBackgroundDrawable(null)進(jìn)行移除
2)復(fù)雜的界面使用自定義View。使用canvas.clipRect()只在可見(jiàn)區(qū)域進(jìn)行繪制会傲,節(jié)約cpu資源锅棕。
- 94 . cpu和gpu的區(qū)別?
cpu是中央處理器淌山,gpu是顯卡裸燎。
- 95 . 應(yīng)用啟動(dòng)的流程?
啟動(dòng)分為熱啟動(dòng)和冷啟動(dòng)泼疑。熱啟動(dòng)不會(huì)創(chuàng)建Application對(duì)象顺少,直接創(chuàng)建Activity
1)啟動(dòng)
2)創(chuàng)建Application對(duì)象 ,同時(shí)啟動(dòng)一個(gè)新進(jìn)程
3)Application的attachBaseContext ():獲取上下文
4)Application的onCreate()
5)Activity的生命周期(測(cè)量王浴,布局脆炎,繪制)
- 96 . Application的生命周期?
1)attachBaseContext ():可獲取上下文
2)onCreate()
3)onLowMemory (): 低內(nèi)存時(shí)調(diào)用
4)onTrimMemory() : 系統(tǒng)要求應(yīng)用釋放內(nèi)存時(shí)調(diào)用
5)onTerminate (): 應(yīng)用結(jié)束時(shí)調(diào)用
- 97 . 應(yīng)用啟動(dòng)耗時(shí)檢測(cè)氓辣?
通過(guò)代碼打點(diǎn)的方式來(lái)準(zhǔn)確的記錄每個(gè)方法的執(zhí)行時(shí)間秒裕,從而知道哪些地方耗時(shí),然后針對(duì)性的優(yōu)化钞啸。
- 98 . 啟動(dòng)優(yōu)化方案几蜻?
1)在SplashActivity啟動(dòng)頁(yè),進(jìn)行底層初始化工作体斩,模塊初始化工作等梭稚。
2)給啟動(dòng)頁(yè)增加個(gè)主題背景,解決啟動(dòng)白屏問(wèn)題
3)根據(jù)任務(wù)必要性絮吵,分地方初始化不同初始工作弧烤。
- 99 .提高ListView的滑動(dòng)平滑度?
在滑動(dòng)時(shí)蹬敲,停止Item上的線程工作暇昂,結(jié)束后莺戒,在繼續(xù)進(jìn)行線程工作。
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING){
workThread(false);
}else {
workThread(true);
}
}
- 100 .android 動(dòng)畫(huà)分幾種急波?
幀動(dòng)畫(huà)从铲,補(bǔ)間動(dòng)畫(huà),屬性動(dòng)畫(huà)澄暮。