????????大學(xué)還沒畢業(yè),卻很幸運地收到一家公司的offer,這是我努力去面試的結(jié)果,原以為我將會走在同學(xué)們的前面一點點,可是好景不長,收到公司的通知----我被炒了!這種心情真的...唉,還是不說了。又要開始準備面試了,既然要準備面試,順帶也整理一下面試內(nèi)容吧!
Activity的生命周期
? ? ? ? 先上一張大眾圖片
? ? ? ? Activity的生命周期有七個過程,onCreate、onStart、onRestart,onResume、onPause、onStop、onDestroy。這樣說誰都會,但是你知道所以然嗎?下面我解析一下,也是從網(wǎng)上查找出來的。
? ? ? ? 1、啟動Activity:系統(tǒng)會調(diào)用onCreate方法,然后調(diào)用onStart方法,最后調(diào)用onResume,Activity進入運行狀態(tài)。
? ? ? ? 2、當前Activity被其他Activity覆蓋其上或鎖屏:系統(tǒng)會調(diào)用onPause方法,暫停當前Activity的執(zhí)行。
? ? ? ? 3、當前Activity由被覆蓋狀態(tài)回到前臺或鎖屏:系統(tǒng)會調(diào)用onResume方法,再次進入運行狀態(tài)
? ? ? ? 4、當前Activity轉(zhuǎn)到新的Activity界面或Home鍵回到主屏,自身退居后臺:系統(tǒng)會先調(diào)用onPause方法,然后調(diào)用onStop方法,進入停滯狀態(tài)。
? ? ? ? 5、用戶后退回到此Activity:系統(tǒng)會先調(diào)用onRestart方法,然后調(diào)用onStart方法,最后調(diào)用onResume方法,再次進入運行狀態(tài)
? ? ? ? 6、當前Activity處于被覆蓋狀態(tài)或者后臺不可見狀態(tài),即第二步和第四步,系統(tǒng)內(nèi)存不足,殺死當前Activity,而后用戶退回當前Activity,再次調(diào)用onCreate方法,onStart方法、onResume,進入運行狀態(tài)。
? ? ? ? 7、用戶退出當前Activity:系統(tǒng)先調(diào)用onPause方法,然后調(diào)用onStop方法,最后調(diào)用onDestroy方法,結(jié)束當前Activity。
Fragment的生命周期
啟動Fragment的時候,先onAttach、onCreate、onCreateView、onActivityCreated、onStart、onResume;
屏幕滅掉的時候,onPause,onSaveInstanceState、onStop
屏幕解鎖的時候,先onStart,onResume
切換到其他Fragment,onPause,onStop、onDestroyView
切換回本身的Fragment,onCreateView,onActivityCreated、onStart、onResume
回到桌面、onPause、onSaveInstanceState、onStop
回到應(yīng)用,onStart、 onResume
退出應(yīng)用 ,onPause,onStop,onDestroyView, onDestroy, onDetach
ANR
????????ANR的定義:在Android上,如果你的應(yīng)用有一段時間不夠靈敏,系統(tǒng)會像用戶顯示一個對話框,這個對話框稱作應(yīng)用程序無響應(yīng)(ANR:Application Not Responding)對話框,用戶可以選擇用程序繼續(xù)運行,但是,他們在使用你的應(yīng)用程序時,并不希望每次都要處理這個對話框。因此,在程序?qū)ο鄳?yīng)性能的設(shè)計很重要,這樣,系統(tǒng)不會顯示ANR給用戶。? ??
? ? ? ? 不同組件發(fā)生ANR的時間不一樣,主線程Activity是5s,BroadCaseReceive是10s。那么解決方案都有哪些呢,其實我覺得沒有具體的解決方案,只是你編程的時候注意些,嚴謹一點,將所有的耗時操作都放在子線程里去操作。如果耗時操作確實要用戶等待,那我覺得在顯示界面上展示一個進度條是個不錯的選擇。
什么情況會導(dǎo)致Force Close ?如何避免?能否捕獲導(dǎo)致其的異常?
? ? ? ? 導(dǎo)致出現(xiàn)Force Close(強行關(guān)閉)的原因有很多,比如NullPointExection(空指針)IndexOutOfBoundsException(角標越界),使用的類沒有找到,使用的資源沒有找到,或者調(diào)用Android api的時候使用順序錯誤也有可能導(dǎo)致、
? ??????避免forceclose方案:首先是盡可能的保證程序不出現(xiàn)這些異常,如果有些異常實在不可避免而又不想讓程序彈出forceclose彈窗,可以使用UncaughtExceptionHandler。當程序出現(xiàn)未捕獲異常時會去調(diào)用UncaughtExctionHandler中的uncaughtException方法,我們要做的就是實現(xiàn)UncaughtExceptionHandler類,自行處理未捕獲異常,代碼請看處理forcelose問題。
橫豎屏切換時候activity的生命周期
? ? ? ? 這個面試題網(wǎng)上到處都有,但是實際面試中好像沒有遇到過。1、不設(shè)置Activity的android:configChanges時,切屏?xí)匦抡{(diào)用各個生命周期,切橫屏?xí)r會執(zhí)行一次,切豎屏?xí)r會執(zhí)行兩次;2、設(shè)置Activity的android:configChanges="orientation"時,切屏還是會重新調(diào)用各個生命周期,切橫、豎屏?xí)r只會執(zhí)行一次;3、設(shè)置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調(diào)用各個生命周期,只會執(zhí)行onConfigurationChanged方法
Handler 、 Looper 、Message 有什么關(guān)系
? ? ? ? 這三者都與Android異步消息處理線程相關(guān)的概念。那什么是異步消息處理線程呢?異步消息處理線程啟動后會進入一個無限循環(huán)體之中,沒循環(huán)一次,從其內(nèi)部的消息隊列中取出一個消息,然后回調(diào)相應(yīng)的消息處理函數(shù),執(zhí)行完成一個消息后則繼續(xù)循環(huán)。若消息隊列為空,線程則會阻塞等待。其實Looper負責的就是創(chuàng)建一個MessageQueue(消息隊列),然后進入一個無限循環(huán)體不斷從該MessageQueue中讀取消息,而消息的創(chuàng)建者就是一個或多個Handler 。
對Android NDK的理解
? ? ? ?Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google稱為“NDK”。
? ? ? ? ?還有些理解就是:1、NDK是系列工具的集合;2、NDK提供了一份穩(wěn)定、功能有限的API頭文件聲明;3、使“Java + C”的開發(fā)方式正式終于轉(zhuǎn)正,成為官方支持的開發(fā)方式;4、NDK將是Android平臺支持C開發(fā)的開端
四大組件,五大存儲、六大布局
? ? ? ? Android的四大組件是activity,service、contentprovider、broadcastreceiver,這四個組件都需要在配置文件(AndroidManifest.xml)中聲明,他們之間通過是用Intent進行通信。
? ? ? ? activity通常就是一個單獨的界面(窗口或屏幕),它是一種可以包含用戶界面的組件,主要用于和用戶進行交互
? ? ? ? service
????????(1)service用于在后臺完成用戶指定的操作。service分為兩種:
????????(a)started(啟動):當應(yīng)用程序組件(如activity)調(diào)用startService()方法啟動服務(wù)時,服務(wù)處于started狀態(tài)。
????????(b)bound(綁定):當應(yīng)用程序組件調(diào)用bindService()方法綁定到服務(wù)時,服務(wù)處于bound狀態(tài)。
????????(2)startService()與bindService()區(qū)別:
????????(a)started service(啟動服務(wù))是由其他組件調(diào)用startService()方法啟動的,這導(dǎo)致服務(wù)的onStartCommand()方法被調(diào)用。當服務(wù)是started狀態(tài)時,其生命周期與啟動它的組件無關(guān),并且可以在后臺無限期運行,即使啟動服務(wù)的組件已經(jīng)被銷毀。因此,服務(wù)需要在完成任務(wù)后調(diào)用stopSelf()方法停止,或者由其他組件調(diào)用stopService()方法停止。
????????(b)使用bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止,大有“不求同時生,必須同時死”的特點。
????????(3)開發(fā)人員需要在應(yīng)用程序配置文件中聲明全部的service,使用標簽。
????????(4)Service通常位于后臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用于為其他組件提供后臺服務(wù)或監(jiān)控其他組件的運行狀態(tài)。
? ??????content provider
????????(1)android平臺提供了Content Provider使一個應(yīng)用程序的指定數(shù)據(jù)集提供給其他應(yīng)用程序。其他應(yīng)用可以通過ContentResolver類從該內(nèi)容提供者中獲取或存入數(shù)據(jù)。
????????(2)只有需要在多個應(yīng)用程序間共享數(shù)據(jù)是才需要內(nèi)容提供者。例如,通訊錄數(shù)據(jù)被多個應(yīng)用程序使用,且必須存儲在一個內(nèi)容提供者中。它的好處是統(tǒng)一數(shù)據(jù)訪問方式。
????????(3)ContentProvider實現(xiàn)數(shù)據(jù)共享。ContentProvider用于保存和獲取數(shù)據(jù),并使其對所有應(yīng)用程序可見。這是不同應(yīng)用程序間共享數(shù)據(jù)的唯一方式,因為android沒有提供所有應(yīng)用共同訪問的公共存儲區(qū)。
????????(4)開發(fā)人員不會直接使用ContentProvider類的對象,大多數(shù)是通過ContentResolver對象實現(xiàn)對ContentProvider的操作。
????????(5)ContentProvider使用URI來唯一標識其數(shù)據(jù)集,這里的URI以content://作為前綴,表示該數(shù)據(jù)由ContentProvider來管理。
? ??????broadcast receiver
? ??????(1)你的應(yīng)用可以使用它對外部事件進行過濾,只對感興趣的外部事件(如當電話呼入時,或者數(shù)據(jù)網(wǎng)絡(luò)可用時)進行接收并做出響應(yīng)。廣播接收器沒有用戶界面。然而,它們可以啟動一個activity或serice來響應(yīng)它們收到的信息,或者用NotificationManager來通知用戶。通知可以用很多種方式來吸引用戶的注意力,例如閃動背燈、震動、播放聲音等。一般來說是在狀態(tài)欄上放一個持久的圖標,用戶可以打開它并獲取消息。
????????(2)廣播接收者的注冊有兩種方法,分別是程序動態(tài)注冊(非常駐型,廣播跟隨程序的生命周期)和AndroidManifest文件中進行靜態(tài)注冊(常駐型,當應(yīng)用程序關(guān)閉后,如果有信息廣播來,程序也會被系統(tǒng)調(diào)用自動運行。)。
????????(3)動態(tài)注冊廣播接收器特點是當用來注冊的Activity關(guān)掉后,廣播也就失效了。靜態(tài)注冊無需擔憂廣播接收器是否被關(guān)閉,只要設(shè)備是開啟狀態(tài),廣播接收器也是打開著的。也就是說哪怕app本身未啟動,該app訂閱的廣播在觸發(fā)時也會對它起作用
? ? ? ? ? 五中存儲方式有SharedPreferences、文件存儲、SQLite方式、內(nèi)容提供器(Content provider)和網(wǎng)絡(luò)存儲。SharedPreferences只能保存在當前應(yīng)用并且被當前應(yīng)用使用。文件存儲是用Android提供的openFileInput和openFileOutput方法讀取設(shè)備上的文件。SQLite是Android所帶的一個標準的數(shù)據(jù)庫,它支持SQL語句。ContentProvider兩個程序之間對于數(shù)據(jù)進交換。外界的程序通過ContentResolver接口可以訪問ContentProvider提供的數(shù)據(jù),在Activity當中通過getContentResolver()可以得到當前應(yīng)用的ContentResolver實例。
? ? ? ? LinearLayout(線性布局)、TableLayout(表格布局)、FragmeLayout(幀布局)、RelativeLayout(相對布局)、GridLayout(網(wǎng)絡(luò)布局)、AbsoluteLayout(絕對布局)。雖然Android上有這些布局,但是說實在的,我用最多的就是線性布局和相對布局,其他的幾乎沒有用過。
Android中的動畫有哪幾類?
? ? ? ? 兩種,一種是Tween動畫,還有一種是Frame動畫。Tween動畫,這種實現(xiàn)方式可以使視圖組件移動、放大、縮小以及產(chǎn)生透明度的變化,Tween動畫在Android中分為4類,它們分別是:AlphaAnimation(透明度動畫)、TranslateAnimation(平移動畫)、ScaleAnimation(縮放動畫)、RotateAnimation(旋轉(zhuǎn)動畫)。都繼承自android.view.Animation類,它們都是表示從一個狀態(tài)A向狀態(tài)B變化的一個過程,所以英文名字叫Tween動畫、中文名叫:“補間動畫”、“中間動畫”;另一種Frame動畫,傳統(tǒng)的動畫方法,通過順序的播放排列好的圖片來實現(xiàn),類似電影。
socktet、tcp/ip、http
? ??????TCP/IP協(xié)議是一個協(xié)議集合,TCP/IP協(xié)議按照層次分為以下四層:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層。http是超文本傳輸協(xié)議,是互聯(lián)網(wǎng)上應(yīng)用最廣泛的以一種網(wǎng)絡(luò)協(xié)議,所有www文件都遵循這個標準。socktet的中文名是套接字,它是網(wǎng)絡(luò)上的兩個程序通過一個雙向的通信連接實現(xiàn)數(shù)據(jù)的交換,這個連接的一端稱為一個socktet。
MVC
? ? ? ? MVC是Model View Controller,即模型-視圖-控制器,是一種軟件框架模式。它是用一種業(yè)務(wù)邏輯、數(shù)據(jù)與界面顯示分離的方法來組織代碼,將眾多的業(yè)務(wù)邏輯聚集到一個部件里面,在需要改進和個性化定制界面及用戶交互的同時,不需要重新編寫業(yè)務(wù)邏輯,達到減少編碼的時間。同時它還提高了應(yīng)用系統(tǒng)的可維護性,可擴展性、可移植性和組件的可復(fù)用性。(為了達到編碼的最高境界,那就是:低藕合,高復(fù)用,易測試,好維護。)這里有位大神寫的非常好,附上鏈接mvp模式是你的救命稻草嗎?
MVP
理解Activity,View,Window三者關(guān)系
? ? ? ? 都是主要用于顯示并與用戶交互的。view主要是用于繪制我們想要的結(jié)果,是一個最基本的ui組件;window簡單來說是一個窗口,它的大小取決于屏幕的大小,但不是絕對的,如對話框等。可以將window理解為一個容器,里面“盛放”這很多view,這view是以樹形結(jié)構(gòu)組織起來的。activity相當于一個界面,可以直接在其里面處理事件。
四種LaunchMode及其使用場景
? ? ? ? standard模式,這是默認模式,每次激活activity時都會創(chuàng)建Activity實力,并放入任務(wù)棧中,這是大都數(shù)Activity都使用的模式。
? ??????singleTop 模式,如果任務(wù)的棧頂正好存放在該Activity的實例,就重用該實例( 會調(diào)用實例的 onNewIntent() )否則就會創(chuàng)建新的實例并放入棧頂,即使棧中已經(jīng)存在該Activity的實例,只要不在棧頂,都會創(chuàng)建新的實例。使用場景如新聞類或者閱讀類App的內(nèi)容頁面。
? ??????singleTask 模式,如果在棧中已經(jīng)有該Activity的實例,就重用該實例(會調(diào)用實例的 onNewIntent() )。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移出棧。如果棧中不存在該實例,將會創(chuàng)建新的實例放入棧中。使用場景如瀏覽器的主界面。不管從多少個應(yīng)用啟動瀏覽器,只會啟動主界面一次,其余情況都會走onNewIntent,并且會清空主界面上面的其他頁面
????????singleInstance 模式,在一個新棧中創(chuàng)建該Activity的實例,并讓多個應(yīng)用共享該棧中的該Activity實例。一旦該模式的Activity實例已經(jīng)存在于某個棧中,任何應(yīng)用再激活該Activity時都會重用該棧中的實例( 會調(diào)用實例的 onNewIntent() )。其效果相當于多個應(yīng)用共享一個應(yīng)用,不管誰激活該 Activity 都會進入同一個應(yīng)用中。使用場景如鬧鈴提醒,將鬧鈴提醒與鬧鈴設(shè)置分離。singleInstance不要用于中間頁面,如果用于中間頁面,跳轉(zhuǎn)會有問題,比如:A -> B (singleInstance) -> C,完全退出后,在此啟動,首先打開的是B。
? ??
Touch事件傳遞機制
public?boolean?dispatchTouchEvent(MotionEventev);??//用來分派eventpublic?boolean?onInterceptTouchEvent(MotionEventev);//用來攔截eventpublic?boolean?onTouchEvent(MotionEventev);//用來處理event
? ??????其中Activity和View控件(TextView)擁有分派和處理事件方法,View容器(LinearLayout)具有分派,攔截,處理事件方法。這里也有個比喻:領(lǐng)導(dǎo)都會把任務(wù)向下分派,一旦下面的人把事情做不好,就不會再把后續(xù)的任務(wù)交給下面的人來做了,只能自己親自做,如果自己也做不了,就只能告訴上級不能完成任務(wù),上級又會重復(fù)他的過程。另外,領(lǐng)導(dǎo)都有權(quán)利攔截任務(wù),對下級隱瞞該任務(wù),而直接自己去做,如果做不成,也只能向上級報告不能完成任務(wù)。
跨進程通訊的幾種方式
1、訪問其他應(yīng)用的Activity,如調(diào)用系統(tǒng)通話應(yīng)用2、ContentProvider,即訪問系統(tǒng)相冊3、廣播,如顯示系統(tǒng)時間4、AIDL服務(wù)。
什么是AIDL呢?
關(guān)于Context,這里有篇很好的文章Context
關(guān)于Intent
? ? ? ? Intent是一個傳遞消息的對象,可以為Intent制定action來啟動其他應(yīng)用,它是Android四大組件通信的橋梁,比如啟動Activity,啟動Service等等。Intent有兩種類,一種是顯式:通過指定具體類名啟動一個組件。顯式Intent一般用于同一應(yīng)用程序內(nèi),因為您可以確定地知道要啟動的組件名。另外,Android 5.0以后規(guī)定必須顯式啟動Service。
一種是隱式:當希望啟動具備某種特性的組件時,可以使用隱式Intent,隱式Intent無需指定類名,通常用于啟動其他應(yīng)用程序的組件,比如您打算啟動一個地圖定位的activity。
Activity意外退出時,如何進行數(shù)據(jù)保存和恢復(fù)?
? ? ? ? onSaveInstanceState方法,創(chuàng)建一個Bundle類型參數(shù),吧數(shù)據(jù)存儲在這個Bundle對象中,這樣即使Activity意外退出的時候或者被系統(tǒng)摧毀,當重新啟動這個Activity而調(diào)用onCreate方法是,上述Bundle對象會作為參數(shù)轉(zhuǎn)遞給onCreate方法,開發(fā)者可以從Bundle對象中取出保存的數(shù)據(jù),利用這些數(shù)據(jù)將Activity恢復(fù)到被摧毀之前的狀態(tài)。
什么是OOM?如何避免OOM?
????????oom,想必大多數(shù)人都遇到這樣的情況,它的概念是內(nèi)存溢出,內(nèi)存占有量超過了java虛擬機分配的最大內(nèi)存。比如創(chuàng)建或解析Bitmap,分配特大的數(shù)組等。避免oom:1、避免對activity的超過生命周期的引用(盡量使用application代替activity)2、在展示高分辨率圖片時,先將圖片進行壓縮到與空間大小相近。3、及時釋放不使用的Bitmap,動態(tài)回收內(nèi)存,方法:bitmap.recycle()4、對適配器視圖進行優(yōu)化處理,避免過多加載數(shù)據(jù)和對象的生成
異步方式
常見的實現(xiàn)異步方式有:AsyncTask、Thread+Handler
常見的耗時操作有哪些:網(wǎng)絡(luò)請求,數(shù)據(jù)庫操作,復(fù)雜的運算等
子線程更新ui的基本方法有哪些:1、Thread + Handler的方式 2、Activity提供的一個簡便的方式來更新UI runOnUiThread(Runnable r); 3、Handler里邊也提供簡便的更新UI的方式handler.post(Runnable r);
runOnUiThread為什么可以用來更新UI?該方法內(nèi)部做了判斷當前線程是否為UI線程的操作不是UI線程則將該action添加到mHandler所在的UI線程的消息隊列中是UI線程,則直接執(zhí)行。
什么情況下會導(dǎo)致內(nèi)存泄露
? ? ? ? 內(nèi)存泄漏的根本原因:長生命周期的對象持有短生命周期的對象,短生命周期就無法及時釋放。I、靜態(tài)集合類引起內(nèi)存泄露主要是hashmap,Vector等,如果是靜態(tài)集合 這些集合沒有及時setnull的話,就會一直持有這些對象。II.remove 方法無法刪除set集 ?Objects.hash(firstName, lastName);經(jīng)過測試,hashcode修改后,就沒有辦法remove了。III. observer 我們在使用監(jiān)聽器的時候,往往是addxxxlistener,但是當我們不需要的時候,忘記removexxxlistener,就容易內(nèi)存leak。廣播沒有unregisterrecevierIV.各種數(shù)據(jù)鏈接沒有關(guān)閉,數(shù)據(jù)庫contentprovider,io,sokect等。cursorV.內(nèi)部類:java中的內(nèi)部類(匿名內(nèi)部類),會持有宿主類的強引用this。所以如果是new Thread這種,后臺線程的操作,當線程沒有執(zhí)行結(jié)束時,activity不會被回收。Context的引用,當TextView 等等都會持有上下文的引用。如果有static drawable,就會導(dǎo)致該內(nèi)存無法釋放。VI.單例單例 是一個全局的靜態(tài)對象,當持有某個復(fù)制的類A是,A無法被釋放,內(nèi)存leak。