安卓面試題及參考答案(2)
安卓面試題及參考答案
安卓面試題及答案(二)
1, 談?wù)勀銓?duì)Activity的理解?
答案:對(duì)于這種“你對(duì)什么什么怎么理解”的面試題,最好的回到方式就是用你自己的理解說(shuō)出來(lái),通俗中夾雜些專業(yè)術(shù)語(yǔ),偶爾再蹦出幾個(gè)英文。當(dāng)然如果你很牛X,你可以往深了說(shuō),只要?jiǎng)e漫無(wú)目的的說(shuō)就行。圍繞一條主線。這其中如果你對(duì)某一方面比較精通,你就應(yīng)該往你精通的方向引。面試官可能就會(huì)順著你的思路走了。不過(guò)現(xiàn)在有很多面試問(wèn)Android方面的知識(shí)不多,問(wèn)java方面的比較多。
通俗的講,Activity就是一個(gè)應(yīng)用程序的門面,也可以理解成就是WEB程序中一個(gè)頁(yè)面,當(dāng)然與web程序中的頁(yè)面不同的是,web中的一個(gè)頁(yè)面可能只是一個(gè)純粹的展示頁(yè)面不與用戶進(jìn)行任何交互,而幾乎所有的Activity都會(huì)與用戶交互。當(dāng)然兩者在架構(gòu)上也有本質(zhì)區(qū)別,Activity與用戶的交互通過(guò)觸發(fā)UI的不同事件完成的。而Web程序是通過(guò)請(qǐng)求,響應(yīng)來(lái)完成交互的。還有在android中顛覆了很多常規(guī)想法,比如在一個(gè)Activity中可以打開(kāi)另一個(gè)不在同一應(yīng)用的Activity。這在其他程序是不可想象的。當(dāng)然這種設(shè)計(jì)的出發(fā)點(diǎn)也是為了節(jié)省系統(tǒng)資源。從View層的角度來(lái)看,Activity承載了與用戶交互的不同控件。從控制層看,也就是內(nèi)部邏輯,Activity需要保持各個(gè)界面的狀態(tài),背后會(huì)做很多持久化的操作。包括妥善管理生命周期的各個(gè)階段。(把生命周期引出來(lái)了,沒(méi)準(zhǔn)就會(huì)問(wèn)你這方面的)。
下面是文檔式的回答:(最好的回答方式兩者結(jié)合)
首先Activity是android四大組件之一。它是單獨(dú)的,作為用戶與程序交互的一個(gè)載體。幾乎所有的Activity都與用戶交互。Activity創(chuàng)建了一個(gè)窗口,你可以通過(guò)setContentView這個(gè)方法將需要的UI放置在窗口。任何一個(gè)應(yīng)用程序都可以調(diào)用單獨(dú)的一個(gè)Activity。
其次,Activity的繼承關(guān)系 Activity→ContextThemeWrapper→ContextWrapper→Context
最后大部分的Activity的子類都需要實(shí)現(xiàn)以下兩個(gè)接口:
onCreate(Bundle savedInstanceState)接口是初始化activity的地方. 在這兒通??梢哉{(diào)用setContentView(int)設(shè)置在資源文件中定義的UI, 使用findViewById(int) 可以獲得UI中定義的窗口.
onPause()接口是使用者準(zhǔn)備離開(kāi)activity的地方,在這兒,任何的修改都應(yīng)該被提交(通常用于ContentProvider保存數(shù)據(jù)).
所有Activity必須在清單文件里注冊(cè)一下才能使用。
2, Activity的生命周期?
答案:在系統(tǒng)中的Activity被一個(gè)Activity棧所管理。當(dāng)一個(gè)新的Activity啟動(dòng)時(shí),將被放置到棧頂,成為運(yùn)行中的Activity,前一個(gè)Activity保留在棧中,不再放到前臺(tái),直到新的Activity退出為止。
Activity有四種本質(zhì)區(qū)別的狀態(tài):
1)在屏幕的前臺(tái)(Activity棧頂),叫做活動(dòng)狀態(tài)或者運(yùn)行狀態(tài)(active or running)
2)如果一個(gè)Activity失去焦點(diǎn),但是依然可見(jiàn)(一個(gè)新的非全屏的Activity 或者一個(gè)透明的Activity 被放置在棧頂),叫做暫停狀態(tài)(Paused)。一個(gè)暫停狀態(tài)的Activity依然保持活力(保持所有的狀態(tài),成員信息,和窗口管理器保持連接),但是在系統(tǒng)內(nèi)存極端低下的時(shí)候?qū)⒈粴⒌簟?/p>
3)如果一個(gè)Activity被另外的Activity完全覆蓋掉,叫做停止?fàn)顟B(tài)(Stopped)。它依然保持所有狀態(tài)和成員信息,但是它不再可見(jiàn),所以它的窗口被隱藏,當(dāng)系統(tǒng)內(nèi)存需要被用在其他地方的時(shí)候,Stopped的Activity將被殺掉。
4)如果一個(gè)Activity是Paused或者Stopped狀態(tài),系統(tǒng)可以將該Activity從內(nèi)存中刪除,Android系統(tǒng)采用兩種方式進(jìn)行刪除,要么要求該Activity結(jié)束,要么直接殺掉它的進(jìn)程。當(dāng)該Activity再次顯示給用戶時(shí),它必須重新開(kāi)始和重置前面的狀態(tài)。
Activity提供了7個(gè)生命周期方法:
onCreate(),onStart(),onResume(),onPause(),onStop(),onDestory(),onRestart()。在這七個(gè)生命周期方法中有三個(gè)關(guān)鍵的循環(huán)。其實(shí)官方給的那張圖畫(huà)得很明白,但估計(jì)很少人能有耐心去揣摩。那就換種方式展現(xiàn)??磮D吧:
1)以下該圖呈現(xiàn)了一個(gè)Activity完整的生命周期,從onCreate(Bundle)開(kāi)始到onDestroy()結(jié)束。Activity在onCreate()設(shè)置所有的“全局”狀態(tài),在 onDestory()釋放所有的資源。
首先我們運(yùn)行程序,這是打開(kāi)MainActivity依次調(diào)用onCreate->onStart->onResume,這時(shí)MainActivity在棧頂,與我們交互的Activity都在棧頂。然后我按下返回鍵,則會(huì)依次調(diào)用onPause->onStop->onDestory。這屬于一個(gè)完整的生命周期。
2)可見(jiàn)的生命周期,從onStart()開(kāi)始到onStop()結(jié)束。說(shuō)白了就是一個(gè)Activity被另一個(gè)activity完全覆蓋掉,然后又重新回到前臺(tái)這個(gè)一個(gè)過(guò)程稱之為可見(jiàn)生命周期。
首先我們打開(kāi)OtherActivity這個(gè)窗口。此時(shí)MainActivity將被覆蓋掉。則會(huì)依次調(diào)用onPause->onStop。在內(nèi)存不足的時(shí)候,系統(tǒng)也會(huì)殺死MainActivity進(jìn)程。
然后,按下返回鍵,MainActivity又回到前臺(tái)此時(shí)會(huì)調(diào)用 onRestart->onStart->onResume。
3)前臺(tái)的生命周期,從onResume()開(kāi)始到onPause()結(jié)束。在這段時(shí)間里,該Activity處于所有Activity的最前面,和用戶進(jìn)行交互。Activity可以經(jīng)常性地在resumed和paused狀態(tài)之間切換。說(shuō)白了就是一個(gè)Activity覆蓋到另一個(gè)Activity上面,但是并沒(méi)有完全覆蓋掉。
首先,我們將OtherActivity打開(kāi),這是OtherActivity以對(duì)話框模式打開(kāi),懸浮在MainActivity上面。直接調(diào)用的onPause()。
然后 我們按下返回鍵,則調(diào)用的onResume。對(duì)于這種沒(méi)用完全覆蓋的狀態(tài)只會(huì)在onPause與onResume兩個(gè)方法之間切換。
注:還有一種特殊情況,當(dāng)屏幕發(fā)生改變的時(shí)候生命周期是怎樣的呢?比如由豎屏調(diào)整為橫屏。生命周期的方法依次用:onPause->onStop->onDestroy->onCreate->onStart->onResume。這么一個(gè)過(guò)程。它會(huì)銷毀掉原先的activity,重新創(chuàng)建。
3, Acitvity啟動(dòng)模式?
答案:對(duì)于這種題,最后就是自己寫個(gè)例子,觀察一下,才能真正明白。
Activty啟動(dòng)提供了四種啟動(dòng)模式。launchMode:
standard:每次啟動(dòng)新的活動(dòng)窗口(new操作)
singleTop:如果在棧頂是目標(biāo)活動(dòng),則直接打開(kāi).否則開(kāi)啟新的活動(dòng)窗口(new).
singleTask和singleInstance基本上相同.差別在于若根活動(dòng)設(shè)置為singleTask時(shí),則由此所開(kāi)啟的活動(dòng)也在同一任務(wù)中,即taskId相同。.而若根活動(dòng)設(shè)置為singleInstance時(shí),由此開(kāi)啟的活動(dòng)在新的任務(wù)中.即棧中只有一個(gè)活動(dòng),taskid不同。.其余情況相同.
4, 在onCreate方法中Bundle savedInstanceState 這個(gè)參數(shù)有什么作用?
答案:在onCreate方法中有saveInstanceState這個(gè)參數(shù),其實(shí)這個(gè)參數(shù)對(duì)應(yīng)兩個(gè)方法。
void onSaveInstanceState(Bundle outState);void onRestoreInstanceState(Bundle savedInstanceState)。當(dāng)某個(gè)activity變得“容易”被系統(tǒng)銷毀時(shí),說(shuō)白了就是系統(tǒng)在內(nèi)存不足或者其他異常情況下把你的Activity銷毀時(shí),將調(diào)用這個(gè)方法。需要注意的是它是系統(tǒng)調(diào)用的,并且你的Activity是被動(dòng)得被銷毀。你可以在銷毀的時(shí)候保存一下數(shù)據(jù)。然后在onCreate方法中拿出來(lái)。那什么情況下能觸發(fā)這兩個(gè)方法呢?
1)、當(dāng)用戶按下HOME鍵時(shí)。
這是顯而易見(jiàn)的,系統(tǒng)不知道你按下HOME后要運(yùn)行多少其他的程序,自然也不知道activity A是否會(huì)被銷毀,故系統(tǒng)會(huì)調(diào)用onSaveInstanceState,讓用戶有機(jī)會(huì)保存某些非永久性的數(shù)據(jù)。以下幾種情況的分析都遵循該原則
2)、長(zhǎng)按HOME鍵,選擇運(yùn)行其他的程序時(shí)。
3)、按下電源按鍵(關(guān)閉屏幕顯示)時(shí)。
4)、從activity A中啟動(dòng)一個(gè)新的activity時(shí)。
5)、屏幕方向切換時(shí),例如從豎屏切換到橫屏?xí)r。
在屏幕切換之前,系統(tǒng)會(huì)銷毀activity A,在屏幕切換之后系統(tǒng)又會(huì)自動(dòng)地創(chuàng)建activity A,所以onSaveInstanceState一定會(huì)被執(zhí)行
總而言之,onSaveInstanceState的調(diào)用遵循一個(gè)重要原則,即當(dāng)系統(tǒng)“未經(jīng)你許可”時(shí)銷毀了你的activity,則onSaveInstanceState會(huì)被系統(tǒng)調(diào)用,這是系統(tǒng)的責(zé)任,因?yàn)樗仨氁峁┮粋€(gè)機(jī)會(huì)讓你保存你的數(shù)據(jù)(當(dāng)然你不保存那就隨便你了)。
至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成對(duì)的被調(diào)用的,onRestoreInstanceState被調(diào)用的前提是,activity A“確實(shí)”被系統(tǒng)銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會(huì)被調(diào)用,例如,當(dāng)正在顯示activity A的時(shí)候,用戶按下HOME鍵回到主界面,然后用戶緊接著又返回到activity A,這種情況下activity A一般不會(huì)因?yàn)閮?nèi)存的原因被系統(tǒng)銷毀,故activity A的onRestoreInstanceState方法不會(huì)被執(zhí)行
另外,onRestoreInstanceState的bundle參數(shù)也會(huì)傳遞到onCreate方法中,你也可以選擇在onCreate方法中做數(shù)據(jù)還原。
5, 談?wù)勀銓?duì)BroadCastRceiver的理解?
答案:廣播接收者,android四大組件之一,也是唯一一個(gè)能動(dòng)態(tài)注冊(cè)的組件。
1)廣播接收者是一個(gè)專注于接收廣播通知信息,并做出對(duì)應(yīng)處理的組件。很多廣播是源自于系統(tǒng)──比如,通知時(shí)區(qū)改變、電池電量低、拍攝了一張照片或者用戶改變了語(yǔ)言選項(xiàng)。應(yīng)用程序也可以進(jìn)行廣播──比如說(shuō),通知其它應(yīng)用程序一些數(shù)據(jù)下載完成并處于可用狀態(tài)。
2)應(yīng)用程序可以擁有任意數(shù)量的廣播接收者以對(duì)所有它感興趣的通知信息予以響應(yīng)。所有的接收器均繼承自BroadcastReceiver基類。
3)廣播接收者沒(méi)有用戶界面。然而,它們可以啟動(dòng)一個(gè)activity來(lái)響應(yīng)它們收到的信息,或者用NotificationManager來(lái)通知用戶。通知可以用很多種方式來(lái)吸引用戶的注意力──閃動(dòng)背燈、震動(dòng)、播放聲音等等。一般來(lái)說(shuō)是在狀態(tài)欄上放一個(gè)持久的圖標(biāo),用戶可以打開(kāi)它并獲取消息。
6, 廣播分幾種?他們有什么區(qū)別?
答案:廣播被分為兩種不同的類型:“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”。普通廣播是完全異步的,可以在同一時(shí)刻(邏輯上)被所有接收者接收到,消息傳遞的效率比較高,但缺點(diǎn)是:接收者不能將處理結(jié)果傳遞給下一個(gè)接收者,并且無(wú)法終止廣播Intent的傳播。
然而有序廣播是按照接收者聲明的優(yōu)先級(jí)別,被接收者依次接收廣播。如:A的級(jí)別高于B,B的級(jí)別高于C,那么,廣播先傳給A,再傳給B,最后傳給C 。優(yōu)先級(jí)別聲明在 intent-filter 元素的 android:priority 屬性中,數(shù)越大優(yōu)先級(jí)別越高,取值范圍:-1000到1000,優(yōu)先級(jí)別也可以調(diào)用IntentFilter對(duì)象的setPriority()進(jìn)行設(shè)置 。有序廣播的接收者可以終止廣播Intent的傳播,廣播Intent的傳播一旦終止,后面的接收者就無(wú)法接收到廣播。
另外,有序廣播的接收者可以將數(shù)據(jù)傳遞給下一個(gè)接收者,如:A得到廣播后,可以往它的結(jié)果對(duì)象中存入數(shù)據(jù),當(dāng)廣播傳給B時(shí),B可以從A的結(jié)果對(duì)象中得到A存入的數(shù)據(jù)。
Context.sendBroadcast()
發(fā)送的是普通廣播,所有訂閱者都有機(jī)會(huì)獲得并進(jìn)行處理。
Context.sendOrderedBroadcast()
發(fā)送的是有序廣播,系統(tǒng)會(huì)根據(jù)接收者聲明的優(yōu)先級(jí)別按順序逐個(gè)執(zhí)行接收者,
前面的接收者有權(quán)終止廣播(BroadcastReceiver.abortBroadcast()),如果廣播被前面的接收者終止,后面的接收者就再也無(wú)法獲取到廣播。對(duì)于有序廣播,前面的接收者可以將數(shù)據(jù)通過(guò)setResultExtras(Bundle)方法存放進(jìn)結(jié)果對(duì)象,然后傳給下一個(gè)接收者,下一個(gè)接收者通過(guò)代碼:Bundle bundle = getResultExtras(true))可以獲取上一個(gè)接收者存入在結(jié)果對(duì)象中的數(shù)據(jù)。
7, 廣播的生命周期?
答案:廣播的生命周期是非常短的,當(dāng)發(fā)送之后intent會(huì)到AndroidManifest.xml文件中找是不是有匹配的action,如果有就會(huì)調(diào)用Receiver ,然后獲得Receiver 對(duì)象,再執(zhí)行onReceive方法,這時(shí)候Receiver對(duì)象就沒(méi)有用了,當(dāng)我們?cè)俅吸c(diǎn)擊按鈕的時(shí)候就會(huì)重新獲得對(duì)象,這就是BroadcastReceiver的生命周期.
在BroadcastReceiver里不能做一些比較耗時(shí)的操作,否側(cè)會(huì)彈出ANR(Application No
Response)的對(duì)話框.
如果需要完成一項(xiàng)比較耗時(shí)的工作,應(yīng)該通過(guò)發(fā)送Intent給Service,由Service來(lái)完成.這里不能使用子線程來(lái)解決,因?yàn)锽roadcastReceiver的生命周期很短,子線程可能還沒(méi)有結(jié)束,BroadcastReceiver就先結(jié)束了.BroadcastReceiver一旦結(jié)束,此時(shí)BroadcastReceiver的所在進(jìn)程很容易在系統(tǒng)需要內(nèi)存時(shí)被優(yōu)先殺死,因?yàn)樗鼘儆诳者M(jìn)程(沒(méi)有任何活動(dòng)組件的進(jìn)程).如果它的宿主進(jìn)程被殺死,那么正在工作的子線程也會(huì)被殺死.所以采用子線程來(lái)解決是不可靠的.
8, 兩種注冊(cè)BroadcastReceiver的方法?
答案:使用在manifest中注冊(cè)的方法注冊(cè)BroadcastReceiver,即使你的應(yīng)用程序沒(méi)有啟動(dòng),或者已經(jīng)被關(guān)閉,這個(gè)BroadcastReceiver依然會(huì)繼續(xù)運(yùn)行,這樣的運(yùn)行機(jī)制可能會(huì)給軟件的用戶造成困擾。所以作為程序的開(kāi)發(fā)者,我們希望能夠有一種靈活的機(jī)制完成BroadcastReceiver的綁定和解除綁定操作。Android當(dāng)然也考慮到了這些問(wèn)題,所以在Context這個(gè)類當(dāng)中提供了如下兩個(gè)函數(shù)可以在代碼中注冊(cè):
i. registerReceiver(receiver,filter);
這個(gè)函數(shù)的作用就是將一個(gè)BroadcastReceiver注冊(cè)到應(yīng)用程序當(dāng)中,這個(gè)函數(shù)接收兩個(gè)參數(shù),第一個(gè)參數(shù)是需要注冊(cè)的BroadcastReceiver對(duì)象,第二個(gè)是一個(gè)IntentFilter。第一個(gè)參數(shù)是非常容易理解的,第二個(gè)參數(shù)的作用是定義了哪些Intent才能觸發(fā)這個(gè)注冊(cè)的BroadcastReceiver對(duì)象。
ii. unregisterReceiver(receiver);
這個(gè)方法就非常的簡(jiǎn)單了,用于解除BroadcastReceiver的綁定狀態(tài)。一旦解除完成,響應(yīng)的BroadcastReceiver就不會(huì)再接收系統(tǒng)所廣播的Intent了。
兩種注冊(cè)BroadcastReceiver的方法
1.在應(yīng)用程序的代碼中進(jìn)行注冊(cè)
注冊(cè)BroadcastReceiver
registerReceiver(receiver,filter);
取消注冊(cè)BroadcastReceiver
unregisterReceiver(receiver);
2.在AndroidManifest.xml當(dāng)中進(jìn)行注冊(cè)
兩種注冊(cè)BroadcastReceiver方法的比較:
現(xiàn)在我們了解了兩種注冊(cè)BroadcastReceiver的方法之后,需要考慮一下這兩種方法適用的場(chǎng)合:
i. 第一種注冊(cè)的方法可以保證在應(yīng)用程序安裝之后,BroadcastReceiver始終處于活動(dòng)狀態(tài),通常用于監(jiān)聽(tīng)系統(tǒng)狀態(tài)的改變,比如說(shuō)手機(jī)的電量,wifi網(wǎng)卡的狀態(tài)(當(dāng)然,監(jiān)視這些東西也是取決于軟件的需求)。對(duì)于這樣的BroadcastReceiver,通常是在產(chǎn)生某個(gè)特定的系統(tǒng)事件之后,進(jìn)行相應(yīng)的操作,比如說(shuō)wifi網(wǎng)卡打開(kāi)時(shí),給用戶一個(gè)提示;
ii. 第二種注冊(cè)方法相對(duì)第一種要靈活的多,這樣注冊(cè)的BroadcastReceiver通常用于更新UI的狀態(tài)。一般來(lái)說(shuō),都是在一個(gè)Activity啟動(dòng)的時(shí)候使用這樣的方法注冊(cè)BroadcastReceiver,一旦接收到廣播的事件,就可以在onReceive方法當(dāng)中更新當(dāng)前的這個(gè)Activity當(dāng)中的控件。但是需要注意的是如果這個(gè)Activity不可見(jiàn)了,就應(yīng)該調(diào)用unregisterReceiver方法來(lái)解除注冊(cè)
9, 粘性廣播有什么作用?怎么使用?
答案:粘性廣播主要為了解決,在發(fā)送完廣播之后,動(dòng)態(tài)注冊(cè)的接收者,也能夠收到廣播。舉個(gè)例子首先發(fā)送一廣播,我的接收者是通過(guò)程序中的某個(gè)按鈕動(dòng)態(tài)注冊(cè)的。如果不是粘性廣播,我注冊(cè)完接收者肯定無(wú)法收到廣播了。這是通過(guò)發(fā)送粘性廣播就能夠在我動(dòng)態(tài)注冊(cè)接收者后也能收到廣播。
用法:
//發(fā)送粘性廣播
Public void sendStickyBroadCast(){
Intent intent=new Intent();
intent.setAction(“com.iteye.myreceiver.action”);
intent.putExtra(“name”,”tom”);
this.sendStickyBroadCast(intent);
}
發(fā)送粘性廣播還需要發(fā)送粘性廣播的權(quán)限:
//動(dòng)態(tài)注冊(cè)廣播接收者
MyReceiver mr = new MyReceiver ();
IntentFilter filter = new IntentFilter();
filter.addAction(“com.iteye.myreceiver.action “);
filter.addCategory(Intent.CATEGORY_DEFAULT);
Intent ii = this.registerReceiver(mr, filter);
String n = ii.getStringExtra(“name”);
Toast.makeText(this, “動(dòng)態(tài)注冊(cè)接收者完成,收到粘性廣播,name=” + n, 1).show();
10,如何控制接收者或者發(fā)送方得權(quán)限?
答案: 1)如果廣播發(fā)送方要求接收方必須有某個(gè)權(quán)限才能收到廣播怎么做呢?
/**
* 發(fā)送廣播,指定接收者權(quán)限
* sendBroadcast(i, “com.iteye.permission.receiver”);//指定接收者權(quán)限
*/
public void sendBroadcast() {
//隱式意圖,發(fā)送廣播
Intent i = new Intent();
i.setAction(“com.iteye.receiver.action”);
i.putExtra(“name”, “tom”);
this.sendBroadcast(i, ” com.iteye.permission.receiver “);
Log.i(“Other”,”.send ok!”);
}
在清單文件里receiver必須有這個(gè)權(quán)限才能收到廣播。
首先,需要定義權(quán)限:
然后,聲明權(quán)限:
這時(shí)接收者就能收到發(fā)送的廣播。
2)反過(guò)來(lái),如果接收者要求發(fā)送方必須擁有某個(gè)權(quán)限,我才接收你的廣播怎么辦呢?
android:permission:控制發(fā)送方需要具備指定權(quán)限,才接收其廣播
即使過(guò)濾器匹配,如果發(fā)送方?jīng)]有相應(yīng)權(quán)限,接收者也不會(huì)接收其廣播。
11.NDK是什么:
答:NDK是一系列工具的集合
NDK提供了一系列的工具,幫助開(kāi)發(fā)者迅速的開(kāi)發(fā)C/C++的動(dòng)態(tài)庫(kù),并能自動(dòng)將so和java應(yīng)用打成apk包
NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件和隔離cpu,平臺(tái)等的差異,開(kāi)發(fā)人員只需簡(jiǎn)單的修改mk文件就可以創(chuàng)建出so
12.描述一下android的系統(tǒng)架構(gòu):
答:android系統(tǒng)架構(gòu)分從下往上為L(zhǎng)inux內(nèi)核層、運(yùn)行庫(kù)、應(yīng)用程序框架層和應(yīng)用程序?qū)印?/p>
Linux內(nèi)核層:負(fù)責(zé)硬件的驅(qū)動(dòng)程序、網(wǎng)絡(luò)、電源、系統(tǒng)安全以及內(nèi)存管理等功能。
運(yùn)行庫(kù)和androidruntion:運(yùn)行庫(kù):即c/c++函數(shù)庫(kù)部分,大多數(shù)都是開(kāi)放源代碼的函數(shù)庫(kù),例如webkit,該函數(shù)庫(kù)負(fù)責(zé)android網(wǎng)頁(yè)瀏覽器的運(yùn)行;例如標(biāo)準(zhǔn)的c函數(shù)庫(kù)libc、openssl、sqlite等,當(dāng)然也包括支持游戲開(kāi)發(fā)的2dsgl和3dopengles,在多媒體方面有mediaframework框架來(lái)支持各種影音和圖形文件的播放與顯示,如mpeg4、h.264、mp3、aac、amr、jpg和png等眾多的多媒體文件格式。Androidruntion負(fù)責(zé)解釋和執(zhí)行生成的dalvik格式的字節(jié)碼
應(yīng)用軟件架構(gòu):java應(yīng)用程序開(kāi)發(fā)人員主要是使用該層封裝好的api進(jìn)行快速開(kāi)發(fā)的。
應(yīng)用程序?qū)樱涸搶邮莏ava的應(yīng)用程序?qū)?,android內(nèi)置的googlemaps、email、IM、瀏覽器等,都處于該層,java開(kāi)發(fā)人員工發(fā)的程序也處于該層,而且和內(nèi)置的應(yīng)用程序具有平等的地位,可以調(diào)用內(nèi)置的應(yīng)用程序,也可以替換內(nèi)置的應(yīng)用程序
13.Activity 與 Task的啟動(dòng)模式有哪些,它們含義具體是什么?
答:在一個(gè)activity中,有多次調(diào)用startActivity來(lái)啟動(dòng)另一個(gè)activity,要想只生成一個(gè)activity實(shí)例,可以設(shè)置啟動(dòng)模式。
一個(gè)activity有四種啟動(dòng)模式:standed,signleTop,singleTask,singleInstance
Standed:標(biāo)準(zhǔn)模式,一調(diào)用startActivity()方法就會(huì)產(chǎn)生一個(gè)新的實(shí)例。
SingleTop:如果已經(jīng)有一個(gè)實(shí)例位于activity棧頂,就不產(chǎn)生新的實(shí)例,而只是調(diào)用activity中的newInstance()方法。如果不位于棧頂,會(huì)產(chǎn)生一個(gè)新的實(shí)例。
singleTask:會(huì)在一個(gè)新的task中產(chǎn)生這個(gè)實(shí)例,以后每次調(diào)用都會(huì)使用這個(gè),不會(huì)去產(chǎn)生新的實(shí)例了。
SingleInstance:這個(gè)和singleTask基本一樣,只有一個(gè)區(qū)別:在這個(gè)模式下的activity實(shí)例所處的task中,只能有這個(gè)activity實(shí)例,不能有其他實(shí)例
14.Application類的作用:
答:API里的第一句是:
Base class for those who need to maintain global application state
如果想在整個(gè)應(yīng)用中使用全局變量,在java中一般是使用靜態(tài)變量,public類型;而在android中如果使用這樣的全局變量就不符合Android的框架架構(gòu),但是可以使用一種更優(yōu)雅的方式就是使用Application context。
首先需要重寫Application,主要重寫里面的onCreate方法,就是創(chuàng)建的時(shí)候,初始化變量的值。然后在整個(gè)應(yīng)用中的各個(gè)文件中就可以對(duì)該變量進(jìn)行操作了。
啟動(dòng)Application時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)PID,即進(jìn)程ID,所有的Activity就會(huì)在此進(jìn)程上運(yùn)行。那么我們?cè)贏pplication創(chuàng)建的時(shí)候初始化全局變量,同一個(gè)應(yīng)用的所有Activity都可以取到這些全局變量的值,換句話說(shuō),我們?cè)谀骋粋€(gè)Activity中改變了這些全局變量的值,那么在同一個(gè)應(yīng)用的其他Activity中值就會(huì)改變
15.說(shuō)明onSaveInstanceState() 和 onRestoreInstanceState()在什么時(shí)候被調(diào)用:
答:Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法,它們并不一定會(huì)被觸發(fā)。當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足、用戶直接按Home鍵)由系統(tǒng)銷毀一個(gè)Activity時(shí),onSaveInstanceState()才會(huì)被調(diào)用。但是當(dāng)用戶主動(dòng)去銷毀一個(gè)Activity時(shí),例如在應(yīng)用中按返回鍵,onSaveInstanceState()就不會(huì)被調(diào)用。因?yàn)樵谶@種情況下,用戶的行為決定了不需要保存Activity的狀態(tài)。通常onSaveInstanceState()只適合用于保存一些臨時(shí)性的狀態(tài),而onPause()適合用于數(shù)據(jù)的持久化保存。
另外,當(dāng)屏幕的方向發(fā)生了改變, Activity會(huì)被摧毀并且被重新創(chuàng)建,如果你想在Activity被摧毀前緩存一些數(shù)據(jù),并且在Activity被重新創(chuàng)建后恢復(fù)緩存的數(shù)據(jù)??梢灾貙慉ctivity的 onSaveInstanceState() 和 onRestoreInstanceState()方法。
16.android的service的生命周期?哪個(gè)方法可以多次被調(diào)用:
答:1)與采用Context.startService()方法啟動(dòng)服務(wù)有關(guān)的生命周期方法
onCreate() -> onStart() -> onDestroy()
onCreate()該方法在服務(wù)被創(chuàng)建時(shí)調(diào)用,該方法只會(huì)被調(diào)用一次,無(wú)論調(diào)用多少次startService()或bindService()方法,服務(wù)也只被創(chuàng)建一次。
onStart() 只有采用Context.startService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在服務(wù)開(kāi)始運(yùn)行時(shí)被調(diào)用。多次調(diào)用startService()方法盡管不會(huì)多次創(chuàng)建服務(wù),但onStart() 方法會(huì)被多次調(diào)用。
onDestroy()該方法在服務(wù)被終止時(shí)調(diào)用。
2)與采用Context.bindService()方法啟動(dòng)服務(wù)有關(guān)的生命周期方法
onCreate() -> onBind() -> onUnbind() -> onDestroy()
onBind()只有采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時(shí)被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用Context.bindService()方法并不會(huì)導(dǎo)致該方法被多次調(diào)用。
onUnbind()只有采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在調(diào)用者與服務(wù)解除綁定時(shí)被調(diào)用。
如果先采用startService()方法啟動(dòng)服務(wù),然后調(diào)用bindService()方法綁定到服務(wù),再調(diào)用unbindService()方法解除綁定,最后調(diào)用bindService()方法再次綁定到服務(wù),觸發(fā)的生命周期方法如下:
onCreate() ->onStart() ->onBind() ->onUnbind()[重載后的方法需返回true] ->onRebind()
17.android的broadcast的生命周期:
答:1)Broadcast receiver生命周期中僅有一個(gè)回調(diào)方法:
void onReceive(Context curContext, Intent broadcastMsg)
當(dāng)接收器接收到一條broadcast消息,Android就會(huì)調(diào)用onReceiver(),并傳遞給它一個(gè)Intent對(duì)象,這個(gè)對(duì)象攜帶著那條broadcast消息。我們認(rèn)為僅當(dāng)執(zhí)行這個(gè)方式時(shí),Broadcast receiver是活動(dòng)的;這個(gè)方法返回時(shí),它就終止了。這就是Broadcast receiver的生命周期。
2)由于Broadcast receiver的生命周期很短,一個(gè)帶有活動(dòng)的Broadcast receiver的進(jìn)程是受保護(hù)的,以避免被干掉;但是別忘了有一點(diǎn),Android會(huì)在任意時(shí)刻干掉那些攜帶不再活動(dòng)的組件的進(jìn)程,所以很可能會(huì)造成這個(gè)問(wèn)題。
3)解決上述問(wèn)題的方案采用一個(gè)Service來(lái)完成這項(xiàng)工作,Android會(huì)認(rèn)為那個(gè)進(jìn)程中(Service所在的進(jìn)程)仍然有在活動(dòng)的組件。
18.android view,surfaceview,glsurfaceview的區(qū)別:
答:SurfaceView是從View基類中派生出來(lái)的顯示類,直接子類有GLSurfaceView和VideoView,可以看出GL和視頻播放以及Camera攝像頭一般均使用SurfaceView
SurfaceView和View最本質(zhì)的區(qū)別在于,surfaceView是在一個(gè)新起的單獨(dú)線程中可以重新繪制畫(huà)面而View必須在UI的主線程中更新畫(huà)面。
那么在UI的主線程中更新畫(huà)面 可能會(huì)引發(fā)問(wèn)題,比如你更新畫(huà)面的時(shí)間過(guò)長(zhǎng),那么你的主UI線程會(huì)被你正在畫(huà)的函數(shù)阻塞。那么將無(wú)法響應(yīng)按鍵,觸屏等消息。
當(dāng)使用surfaceView 由于是在新的線程中更新畫(huà)面所以不會(huì)阻塞你的UI主線程。但這也帶來(lái)了另外一個(gè)問(wèn)題,就是事件同步。比如你觸屏了一下,你需要surfaceView中thread處理,一般就需要有一個(gè)event queue的設(shè)計(jì)來(lái)保存touch event,這會(huì)稍稍復(fù)雜一點(diǎn),因?yàn)樯婕暗骄€程同步。
所以基于以上,根據(jù)游戲特點(diǎn),一般分成兩類。
1)被動(dòng)更新畫(huà)面的。比如棋類,這種用view就好了。因?yàn)楫?huà)面的更新是依賴于 onTouch 來(lái)更新,可以直接使用 invalidate。 因?yàn)檫@種情況下,這一次Touch和下一次的Touch需要的時(shí)間比較長(zhǎng)些,不會(huì)產(chǎn)生影響。
2)主動(dòng)更新。比如一個(gè)人在一直跑動(dòng)。這就需要一個(gè)單獨(dú)的thread不停的重繪人的狀態(tài),避免阻塞main UI thread。所以顯然view不合適,需要surfaceView來(lái)控制。
看過(guò)“安卓面試題及答案”的人還看了:
1.安卓面試題及答案
2.關(guān)于Android開(kāi)發(fā)工程師的面試題
3.安卓面試題及答案