匯總一下Android面試題疚俱,并逐漸補(bǔ)充答案书在。
最近比較忙甘穿,沒(méi)有進(jìn)一步整理腮恩,不過(guò)沒(méi)有答案的題目也可以作為復(fù)習(xí)引導(dǎo)來(lái)用,后續(xù)有時(shí)間在補(bǔ)充吧温兼。
Android:
1. 說(shuō)一下四大組件秸滴。
四大組件指Activity、Service募判、BroadcastReceiver荡含、ContentProvider,這四大組件都需要在AndroidManifest文件中注冊(cè)才可以使用兰伤。
2. Activity生命周期和四種啟動(dòng)模式内颗。
生命周期:
onCreate: Activity第一次創(chuàng)建時(shí)必然執(zhí)行的方法,我們?cè)谶@個(gè)方法中做一下初始化的操作敦腔,例如加載布局均澳,初始化控件,注冊(cè)點(diǎn)擊事件等符衔。
onStart: 當(dāng)Activity變?yōu)榭梢?jiàn)時(shí)調(diào)用該方法找前。
onRestart: 該方法在Activity由停止?fàn)顟B(tài)轉(zhuǎn)變?yōu)檫\(yùn)行狀態(tài)時(shí)調(diào)用,也就是說(shuō)一個(gè)處于后臺(tái)的Activity被重新啟用了判族。(注意:后續(xù)還會(huì)調(diào)用onStart躺盛,不要以為onRestart之后就直接調(diào)用onResume了。)
onResume: 當(dāng)Activity準(zhǔn)備好和用戶交互的時(shí)候調(diào)用形帮,此時(shí)Activity必然處于棧頂槽惫,處于運(yùn)行狀態(tài)。
onPause: 當(dāng)Activity不可交互時(shí)調(diào)用辩撑。例如被銷毀時(shí)界斜、按Home鍵返回桌面時(shí),啟動(dòng)或者恢復(fù)某個(gè)Activity時(shí)合冀。(注意:展示Dialog時(shí)不會(huì)調(diào)用onPasuse各薇,有疑問(wèn)可以自己測(cè)試。)
onStop: 該方法在Activity完全不可見(jiàn)的時(shí)候調(diào)用君躺。它和onPause()方法的主要區(qū)別在于峭判,如果啟動(dòng)的新Activity是一個(gè)對(duì)話框式的activity,那么棕叫,onPause()方法會(huì)得到執(zhí)行林螃,而onStop()方法并不會(huì)執(zhí)行。
onDestroy: 這個(gè)方法在Activity被銷毀之前調(diào)用俺泣,之后Activity的狀態(tài)將變?yōu)殇N毀狀態(tài)治宣。
啟動(dòng)模式:
Standard模式:
標(biāo)準(zhǔn)模式急侥,Standard模式是Android的默認(rèn)啟動(dòng)模式,無(wú)需再M(fèi)anifest文件中配置侮邀,這種模式下坏怪,Activity可以有多個(gè)實(shí)例,每次啟動(dòng)Activity绊茧,無(wú)論任務(wù)棧中是否已經(jīng)有這個(gè)Activity的實(shí)例铝宵,系統(tǒng)都會(huì)創(chuàng)建一個(gè)新的Activity實(shí)例。
SingleTop模式:
棧頂復(fù)用模式华畏,該模式需要在Manifest文件中配置鹏秋。
SingleTop模式和standard模式非常相似,主要區(qū)別就是當(dāng)一個(gè)singleTop模式的Activity已經(jīng)位于任務(wù)棧的棧頂亡笑,再去啟動(dòng)它時(shí)侣夷,不會(huì)再創(chuàng)建新的實(shí)例,如果不位于棧頂,就會(huì)創(chuàng)建新的實(shí)例仑乌。
SingleTask模式:
棧內(nèi)復(fù)用模式百拓,該模式需要在Manifest文件中配置。
SingleTask模式的Activity在同一個(gè)Task內(nèi)只有一個(gè)實(shí)例晰甚,如果Activity已經(jīng)位于棧頂衙传,系統(tǒng)不會(huì)創(chuàng)建新的Activity實(shí)例,和singleTop模式一樣厕九。但Activity已經(jīng)存在但不位于棧頂時(shí)蓖捶,系統(tǒng)就會(huì)把該Activity移到棧頂,并把它上面的activity出棧扁远。
SingleInstance模式:
單例模式俊鱼,該模式需要在Manifest文件中配置。
SingleInstance模式也是棧內(nèi)單例的畅买,但和SingleTask不同并闲,SingleTask只是任務(wù)棧內(nèi)單例,其棧內(nèi)是可以有多個(gè)其他Activity實(shí)例的皮获,且若有別的任務(wù)棧焙蚓,其中也可能有該Activity纹冤;而SingleInstance模式的 Activity在整個(gè)系統(tǒng)里只有一個(gè)實(shí)例洒宝,切啟動(dòng)一SingleInstance模式的Activity時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)新的任務(wù)棧萌京,并且這個(gè)任務(wù)棧只有他一個(gè)Activity雁歌。
3. Activity的啟動(dòng)過(guò)程(不要回答生命周期)。
Activity的啟動(dòng)過(guò)程知残,我們可以從Context的startActivity說(shuō)起靠瞎,其實(shí)現(xiàn)是ContextImpl的startActivity,然后內(nèi)部會(huì)通過(guò)Instrumentation來(lái)嘗試啟動(dòng)Activity,這是一個(gè)跨進(jìn)程過(guò)程乏盐,它會(huì)調(diào)用ams的startActivity方法佳窑,當(dāng)ams校驗(yàn)完activity的合法性后,會(huì)通過(guò)ApplicationThread回調(diào)到我們的進(jìn)程父能,這也是一次跨進(jìn)程過(guò)程神凑,而applicationThread就是一個(gè)binder,回調(diào)邏輯是在binder線程池中完成的何吝,所以需要通過(guò)Handler H將其切換到ui線程溉委,第一個(gè)消息是LAUNCH_ACTIVITY,它對(duì)應(yīng)handleLaunchActivity爱榕,在這個(gè)方法里完成了Activity的創(chuàng)建和啟動(dòng)瓣喊,接著,在activity的onResume中黔酥,activity的內(nèi)容將開(kāi)始渲染到window上藻三,然后開(kāi)始繪制直到我們看見(jiàn)。
轉(zhuǎn)自:https://blog.csdn.net/u010648159/article/details/81103092
4. Service的啟動(dòng)方式及生命周期(參考下方示例代碼)絮爷。
Service的啟動(dòng)方式分為startService和bindService兩種:
startService方式:生命周期為onCreate -> onStartCommand -> onDestroy趴酣。
bindService方式:生命周期為onCreate -> onBind -> onUnbind -> onDestroy。
注意:多次startService或者bindService坑夯,onCreate方法也只會(huì)調(diào)用一次岖寞。
也可以混合啟動(dòng):
先bind后start:生命周期為onCreate -> onBind -> onStartCommand。
先start后bind:生命周期為onCreate -> onStartCommand -> onBind柜蜈。
至于混合啟動(dòng)后的unbind和stop操作仗谆,結(jié)果都是一樣的:
如果先unbind,后stop:則會(huì)依次執(zhí)行onUnbind和onDestroy方法淑履。
但是如果先stop隶垮,后unbind:則會(huì)有所不同:試圖stop時(shí),并沒(méi)有任何反應(yīng)秘噪,但是接下來(lái)unbind到時(shí)候狸吞,會(huì)在調(diào)用onUnbind后,直接調(diào)用onDestroy方法指煎。
示例代碼:
/*=============MainActivity=============*/
//開(kāi)啟服務(wù)
fun startService(){
val intent = Intent(this, MyService::class.java)
startService(intent)
}
//停止服務(wù)
fun stopService(){
val intent = Intent(this, MyService::class.java)
stopService(intent)
}
//綁定服務(wù)
fun bindService() {
if (conn == null) {
val intent = Intent(this, MyService::class.java)
conn = object : ServiceConnection{
override fun onServiceDisconnected(name: ComponentName?) {
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
myIBinder = service as MyService.MyIBinder
}
}
bindService(intent, conn!!, Context.BIND_AUTO_CREATE)
}
}
//解綁服務(wù)
fun unbindService(){
if (conn != null) {
unbindService(conn!!)
conn = null
}
}
/*=============MainActivity=============*/
/*=============MyService=============*/
override fun onCreate() {
super.onCreate()
loge("onCreate")
}
override fun onBind(intent: Intent?): IBinder? {
loge("onBind")
return MyIBinder()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
loge("onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onUnbind(intent: Intent?): Boolean {
loge("onUnbind")
return super.onUnbind(intent)
}
override fun onDestroy() {
super.onDestroy()
loge("onDestroy")
}
/*=============MyService=============*/
5. BroatcastReceiver的注冊(cè)方式蹋偏。
BroatcastReceiver的注冊(cè)方式分為靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)兩種。
動(dòng)態(tài)注冊(cè)廣播不是常駐型廣播至壤,也就是說(shuō)廣播跟隨Activity的生命周期威始。注意在Activity結(jié)束前,移除廣播接收器像街。 靜態(tài)注冊(cè)是常駐型黎棠,也就是說(shuō)當(dāng)應(yīng)用程序關(guān)閉后晋渺,如果有合適的廣播,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行脓斩。
當(dāng)廣播為有序廣播時(shí):優(yōu)先級(jí)高的先接收(不分靜態(tài)和動(dòng)態(tài))木西。同優(yōu)先級(jí)的廣播接收器,動(dòng)態(tài)優(yōu)先于靜態(tài)
同優(yōu)先級(jí)的同類廣播接收器随静,靜態(tài):先掃描的優(yōu)先于后掃描的户魏,動(dòng)態(tài):先注冊(cè)的優(yōu)先于后注冊(cè)的。
當(dāng)廣播為默認(rèn)廣播時(shí):無(wú)視優(yōu)先級(jí)挪挤,動(dòng)態(tài)廣播接收器優(yōu)先于靜態(tài)廣播接收器叼丑。同優(yōu)先級(jí)的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的扛门,動(dòng)態(tài):先注冊(cè)的優(yōu)先于后冊(cè)的鸠信。
6. ContentProvider:
相關(guān)文章:http://www.reibang.com/p/380231307070
8. 子線程能更新UI嗎?
Android的單線程模型模型要求必須要在UI線程更新UI论寨,否則認(rèn)為是不安全的星立,原則上子線程是不能更新UI的。在其他線程訪問(wèn)UI葬凳,Android給提供了如下一些方法:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
- Handler
說(shuō)道低都是調(diào)度到主線程來(lái)完成更新UI的工作绰垂。
其實(shí)如果非要直接在子線程強(qiáng)行更新UI,則會(huì)得到一個(gè)異常:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
實(shí)際上火焰,通過(guò)CalledFromWrongThreadException的堆棧信息可以追蹤ViewRootImpl這個(gè)類劲装,實(shí)際上到這個(gè)是通過(guò)其中的一個(gè)checkThread方法,來(lái)檢查當(dāng)前訪問(wèn)的線程昌简,如果不是UI線程占业,就會(huì)拋出該異常。
回到問(wèn)題本身纯赎,子線程真的不能更新UI嗎谦疾?
實(shí)際上在如下情況中子線程是可以更新的UI的:
在Activity執(zhí)行onCreate時(shí),ViewRootImpl還沒(méi)有實(shí)例化犬金,加入此時(shí)立即new一個(gè)Thread更新UI念恍,則不會(huì)拋出異常。
另外晚顷,如果我們能夠通過(guò)某種方法峰伙,在子線程中擁有ViewRootImpl,那么也可以更新UI音同,具體方法就不深究了词爬。
7. Java虛擬機(jī)和Dalvik虛擬機(jī)和Art的區(qū)別秃嗜。
相關(guān)文章:
http://www.reibang.com/p/713d24fa9982
https://blog.csdn.net/evan_man/article/details/52414390
8. 進(jìn)程和線程权均。
進(jìn)程就是一個(gè)應(yīng)用程序在處理機(jī)上的一次執(zhí)行過(guò)程顿膨,它是一個(gè)動(dòng)態(tài)的概念,而線程是進(jìn)程中的一部分叽赊,一個(gè)進(jìn)程可以包含多個(gè)線程恋沃。
進(jìn)程和線程的關(guān)系和區(qū)別如下:
- 進(jìn)程是cpu資源分配的最小單位, 線程是cpu調(diào)度的最小單位必指。
- 線程是進(jìn)程的子集囊咏,一個(gè)進(jìn)程可以有很多線程,每條線程并行執(zhí)行不同的任務(wù)塔橡。
- 不同的進(jìn)程使用不同的內(nèi)存空間梅割,而所有的線程共享一片相同的內(nèi)存空間。
- 進(jìn)程之間不能共享資源葛家,而線程共享所在進(jìn)程的內(nèi)存空間和其它資源户辞。
- 一個(gè)進(jìn)程內(nèi)可擁有多個(gè)線程,可開(kāi)啟新的進(jìn)程癞谒,也可開(kāi)啟線程底燎。
- 一個(gè)線程只能屬于一個(gè)進(jìn)程,線程可直接使用同進(jìn)程的資源,線程依賴于進(jìn)程而存在弹砚。
9. 進(jìn)程彼裕活(不死進(jìn)程)。
首先明確一點(diǎn)桌吃,“不死進(jìn)程”本身其實(shí)是一個(gè)偽命題朱沃,盡量?jī)?yōu)化APP自身才是正道。
首先說(shuō)一下進(jìn)程的優(yōu)先級(jí):
根據(jù)進(jìn)程的重要性茅诱,劃分5級(jí)为流,優(yōu)先級(jí)依次遞減:
前臺(tái)進(jìn)程 (Foreground process)
可見(jiàn)進(jìn)程 (Visible process)
服務(wù)進(jìn)程 (Service process)
后臺(tái)進(jìn)程 (Background process)
空進(jìn)程 (Empty process)
保活手段:
當(dāng)前業(yè)界的Android進(jìn)程比貌荆活手段主要分為** 黑敬察、白、灰 **三種尔当,其大致的實(shí)現(xiàn)思路如下:
- 黑色绷觯活:不同的app進(jìn)程,用廣播相互喚醒(包括利用系統(tǒng)提供的廣播進(jìn)行喚醒)
所謂黑色蓖钟活锐帜,就是利用不同的app進(jìn)程使用廣播來(lái)進(jìn)行相互喚醒。舉個(gè)3個(gè)比較常見(jiàn)的場(chǎng)景:
場(chǎng)景1:開(kāi)機(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ā)散開(kāi)去建炫,就會(huì)直接觸發(fā)了下面的 場(chǎng)景3
場(chǎng)景3:假如你手機(jī)里裝了支付寶畦韭、淘寶、天貓肛跌、UC等阿里系的app艺配,那么你打開(kāi)任意一個(gè)阿里系的app后,有可能就順便把其他阿里系的app給喚醒了衍慎。(只是拿阿里打個(gè)比方转唉,其實(shí)BAT系都差不多)
- 白色保活:?jiǎn)?dòng)前臺(tái)Service
白色蔽壤Γ活手段非常簡(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)。如音樂(lè)APP的可操作的通知驯嘱。
- 灰色毕獍活:利用系統(tǒng)的漏洞啟動(dòng)前臺(tái)Service
灰色保活鞠评,這種泵荆活手段是應(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ú)法察覺(jué)到你運(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處理
下面補(bǔ)充一下Android的殺進(jìn)程機(jī)制:
熟悉Android系統(tǒng)的童鞋都知道,系統(tǒng)出于體驗(yàn)和性能上的考慮朝捆,app在退到后臺(tái)時(shí)系統(tǒng)并不會(huì)真正的kill掉這個(gè)進(jìn)程般渡,而是將其緩存起來(lái)。打開(kāi)的應(yīng)用越多,后臺(tái)緩存的進(jìn)程也越多驯用。在系統(tǒng)內(nèi)存不足的情況下脸秽,系統(tǒng)開(kāi)始依據(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ī)制誕生贷盲。
了解完 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è)徹頭徹尾的偽命題呈枉!
10. 講解一下Context寸士。
先來(lái)看一下Context家族的繼承樹(shù)結(jié)構(gòu):
可以看出,Context的直接子類有兩個(gè)碴卧,分別為ContextWrapper弱卡,一個(gè)是ContextImpl。顧名思義住册,ContextWrapper是Context的包裝(封裝)類婶博,ContextImpl是Context的實(shí)現(xiàn)類。
可以看到ContextWrapper有三個(gè)直接的子類荧飞,ContextThemeWrapper凡人、Service和Application名党。其中,ContextThemeWrapper是一個(gè)帶主題的封裝類挠轴,而它有一個(gè)直接子類就是Activity传睹。
所以在Android工程中,Context只有3中來(lái)源或者說(shuō)3中類型岸晦,分別是:Application欧啤,Activity,Service启上。那么也就不難統(tǒng)計(jì)真正的Context的數(shù)量了:
Context數(shù)量 = Activity數(shù)量 + Service數(shù)量 + 1(Application)邢隧。
那么ContextImpl是怎么回事呢,前面說(shuō)了冈在,這是一個(gè)Context的實(shí)現(xiàn)類倒慧,由它來(lái)具體實(shí)現(xiàn)了Context中定義的各種方法,而ContextWrapper是Context的包裝類包券,我們看一看ContextWrapper的源碼就會(huì)發(fā)現(xiàn)纫谅,其中有一個(gè)Context成員變量mBase,ContextWrapper將Context方法的實(shí)現(xiàn)全部委托給mBase負(fù)責(zé)溅固,其中有一個(gè)方法attachBaseContext——用來(lái)給mBase賦值系宜,且只能賦值一次,否則會(huì)拋異常发魄,另有一個(gè)方法getBaseContext盹牧,可以用來(lái)獲取mBase。
//=========ContextWrapper部分代碼=========
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return mBase;
}
@Override
public AssetManager getAssets() {
return mBase.getAssets();
}
@Override
public Resources getResources() {
return mBase.getResources();
}
@Override
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
//=========ContextWrapper部分代碼=========
各種Context的作用:
使用場(chǎng)景 | Application | Activity | Service | ContentProvider | BroadcastReceiver |
---|---|---|---|---|---|
Show a Dialog | N | Y | N | N | N |
Start an Activity | N(1) | Y | N(1) | N(1) | N(1) |
Layout Inflation | N(2) | Y | N(2) | N(2) | N(2) |
Start a Service | Y | Y | Y | Y | Y |
Bind a Service | Y | Y | Y | Y | N |
Send a Broadcast | Y | Y | Y | Y | Y |
Register Broadcast Receiver | Y | Y | Y | Y | N(3) |
Load Resource Value | Y | Y | Y | Y | Y |
注:其中ContentProvider励幼,BroadcastReceiver指的內(nèi)部方法中做為參數(shù)傳遞進(jìn)來(lái)的Context汰寓。
大家注意看到有一些NO后面的括號(hào)添加了一些數(shù)字,其實(shí)這些從能力上來(lái)說(shuō)是YES苹粟,但是為什么說(shuō)是NO呢有滑?下面一個(gè)一個(gè)解釋:
N(1):?jiǎn)?dòng)Activity在這些類中是可以的,但是需要?jiǎng)?chuàng)建一個(gè)新的task嵌削。一般情況不推薦毛好。
N(2):在這些類中去layout inflate是合法的,但是會(huì)使用系統(tǒng)默認(rèn)的主題樣式苛秕,如果你自定義了某些樣式可能不會(huì)被使用肌访。
N(3):在receiver為null時(shí)允許,在4.2或以上的版本中艇劫,用于獲取黏性廣播的當(dāng)前值吼驶。(可以無(wú)視)
可以看出:和UI相關(guān)的方法基本都不建議或者不可使用Application,并且,前三個(gè)操作基本不可能在Application中出現(xiàn)蟹演。實(shí)際上风钻,只要把握住一點(diǎn),凡是跟UI相關(guān)的酒请,都應(yīng)該使用Activity做為Context來(lái)處理
11. 理解Activity骡技,View,Window三者關(guān)系羞反。
12. View的繪制流程布朦。
13. View,ViewGroup事件分發(fā)苟弛。
14. 簡(jiǎn)述如何自定義控件喝滞。
14. 保存Activity狀態(tài)阁将。
15. Android中的幾種動(dòng)畫(huà)膏秫。
16. Android中跨進(jìn)程通訊的幾種方式。
17. AIDL理解(此處延伸:簡(jiǎn)述Binder)做盅。
18. Handler的工作原理缤削。
19. Android內(nèi)存泄露及管理。
20. Fragment與Fragment吹榴、Activity通信的方式亭敢。
21. Android UI適配。
字體使用sp,使用dp图筹,多使用match_parent帅刀,wrap_content,weight
圖片資源远剩,不同圖片的的分辨率扣溺,放在相應(yīng)的文件夾下」衔睿可使用百分比代替锥余。
相關(guān)文章:http://www.reibang.com/p/a4b8e4c5d9b0?tdsourcetag=s_pcqq_aiomsg