天天看點

安卓面試基礎(如會必過)

Activity

1、 什麼是Activity?

Activity是四大元件之一,他給使用者的感受就是一個使用者互動界面。一個Activity就是一個可見的界面。

他的特點是:1、可見 2、可互動

他之是以可互動,是因為他同時實作了Window.Callback和KeyEvent.Callback, 可以處理與窗體使用者互動的事件和按鍵事件.這兩個特點,是他和service最大的差別。

一個Activity在建立于銷毀的過程中,會經曆一些生命周期。

如果界面有共同的特點或者功能的時候,還會自己定義一個BaseActivity.

安卓面試基礎(如會必過)

2、Activity的生命周期

a、簡述一下生命周期

生命周期描述的是一個類 從建立(new出來)到死亡(垃圾回收)的過程中會執行的方法…

在這個過程中 會針對不同的生命階段會調用不同的方法

Activity從建立到銷毀有多種狀态,從一種狀态到另一種狀态時會激發相應的回調方法,這些回調方法包括:onCreate onDestroy onStop onStart onResume onPause onRestart

當從A界面跳轉到B界面的時候,A界面會調用onPause onStop B界面會調用onCreate、onStart、onResume等。在回到A界面的時候,A界面會調用onReStart、onStart、onResume

如果B界面是透明的activity,那麼進行跳轉的時候,A界面是不會調用onStop的,隻會調用onPause 再回到A界面的時候,A界面會調用onResume

b、A界面跳轉到B界面的時候,再回到A界面,A界面必然會執行的是哪幾個方法。

兩個Activity之間的跳轉必然會執行的是onResume方法,這個具體的應用場景是每次回到該界面的時候,如果界面需要展示最新的資料,那麼可以在該方法中實作。

多媒體播放視訊的時候, 來了一個電話. onStop() 視訊, 視訊聲音設定為0 , 記錄視訊播放的位置 mediaplayer.pause();

onResume() 根據儲存的狀态恢複現場. mediaplayer.start();

c、在螢幕旋轉的時候,activity的生命周期是怎樣的?

橫豎屏進行切換的時候,預設的情況下,Activity會重新的調用onCreate方法。因為豎屏的activity銷毀了,再生成一個橫屏的activity 。

在AndroidManifest.xml可以進行配置,我們可以通過android:configChanges進行配置。android:configChanges=“orientation|keyboardHidden|screenSize” 配置了之後,橫豎屏切換的時候,就不會調用onCreate了,而是調用onConfigurationChanged的方法。

在一些特殊應用中,螢幕的方向是寫死的,比如遊戲。在AndroidManifest中配置android:screenOrientation=“landscape"就可以了。

d、講一講你對activity的了解

e、設定activity的樣式為視窗的樣式,對生命周期有什麼影響?

設定視窗樣式,需要在配置檔案中增加theme的屬性

android:theme=”@android:style/Theme.Dialog"

activity設定為視窗樣式的時候,當啟動這個activity的時候,之前那個activity是不會走onStop方法的,而是隻走到了onPause方法。

3、你背景的Activity被系統 回收如何在被系統回收之前儲存目前狀态?

安卓面試基礎(如會必過)

除了在棧頂的activity,其他的activity在系統資源匮乏的時候,都有可能會被系統回收。這時候系統會調用onSaveInstanceState方法,我們可以往bundle裡面存放資料。在activity onCreate裡面我們先判斷一下bundle是不是為空,如果不為空,就代表這個activity之前被系統回收掉,應該恢複一下現場。我們就可以從bundle裡面取值。

4、對android主線程的運用和了解

a、主線程也就是UI線程,四大元件都是運作在主線程中的。

b、主線程中有一個消息隊列,主要處理視窗繪制、按鈕響應等消息。

c、如果在主線程裡面做耗時的操作,會導緻視窗繪制等消息得不到及時的處理,進而有可能會報出anr的錯誤。

安卓面試基礎(如會必過)

5、如何避免anr?如何解決anr?

anr是android not response 安卓無響應,這裡指的是主線程無響應。将耗時的操作放在子線程中進行可以有效的避免anr。如果出現了anr,我們可以通過log資訊以及traces.txt檔案進行分析。

traces.txt裡面記錄的是stack資訊。

6、Activity的資料傳遞

a、基礎的資料類型通過Bundle進行傳遞

b、傳遞對象的話,需要該對象實作Serializable或者Parcelable接口,放到bundle進行傳遞。

c、在Application中進行存儲。其他界面要用的話,就直接來application取就可以了。一個應用程式application的執行個體隻有一個。

d、大對象,比如bitmap,我們一般都不傳遞這個對象,我們傳遞的一般都是路徑就可以了。然後通過URI.fromFile()來傳遞URI

  1. 如何退出Activity?

    退出activity我們隻需要調用finish就可以了。退出activity 會執行 onDestroy()方法。

    如何一次性的退出多個Activity?

    a、抛異常強制退出:

    該方法通過抛異常,使程式Force Close。

    驗證可以,但是,需要解決的問題是,如何使程式結束掉,而不彈出Force Close的視窗。

    b、記錄打開的Activity:

    每打開一個Activity,就記錄下來。放到application裡面去存起來。在需要退出時,關閉每一個Activity即可。

    8、Activity的啟動模式

    首先我們來看下Task的定義,Google是這樣定義Task的:a task is what the user experiences as an “application.” It’s a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 這意思就是說Task實際上是一個Activity棧,通常使用者感受的一個Application就是一個Task。從這個定義來看,Task跟Service或者其他Components是沒有任何聯系的,它隻是針對Activity而言的。

    Activity有不同的啟動模式, 可以影響到task的配置設定

    Task,簡單的說,就是一組以棧的模式聚集在一起的Activity元件集合。它們有潛在的前後驅關聯,新加入的Activity元件,位于棧頂,并僅有在棧頂的Activity,才會有機會與使用者進行互動。而當棧頂的Activity完成使命退出的時候,Task會将其退棧,并讓下一個将跑到棧頂的Activity來于使用者面對面,直至棧中再無更多Activity,Task結束。

standard", “singleTop”, “singleTask”, “singleInstance”。

standard模式, 是預設的也是标準的Task模式,在沒有其他因素的影響下,使用此模式的Activity,會構造一個Activity的執行個體,加入到調用者的Task棧中去,對于使用頻度一般開銷一般什麼都一般的Activity而言,standard模式無疑是最合适的,因為它邏輯簡單條理清晰,是以是預設的選擇。

而singleTop模式,基本上于standard一緻,僅在請求的Activity正好位于棧頂時,有所差別。此時,配置成singleTop的Activity,不再會構造新的執行個體加入到Task棧中,而是将新來的Intent發送到棧頂Activity中,棧頂的Activity可以通過重載onNewIntent來處理新的Intent(當然,也可以無視…)。這個模式,降低了位于棧頂時的一些重複開銷

singleTask,和singleInstance,則都采取的另辟Task的蹊徑。

标志為singleTask的Activity,最多僅有一個執行個體存在,并且,位于以它為根的Task中。所有對該Activity的請求,都會跳到該Activity的Task中展開進行。singleTask,很象概念中的單件模式,所有的修改都是基于一個執行個體,這通常用在構造成本很大,但切換成本較小的Activity中。最典型的例子,還是浏覽器應用的主Activity(名為Browser…),它是展示目前tab,目前頁面内容的視窗。它的構造成本大,但頁面的切換還是較快的,于singleTask相配,還是挺天作之合的。

singleInstance顯得更為極端一些。在大部分時候singleInstance與singleTask完全一緻,唯一的不同在于,singleInstance的Activity,是它所在棧中僅有的一個Activity, 這個棧,隻有一個activity

activity是運作在任務棧中的,一個activity啟動另外一個activity,預設的情況下,新的activity也是運作在同一個任務棧裡的。service和廣播接收者也是沒有任務棧的,是以,他們啟動activity的時候,給intent設定flag, Intent的flag添加FLAG_ACTIVITY_NEW_TASK

Service

9、什麼是Service以及描述下它的生命周期?

service是一個服務,它是不可見的,同樣也是運作在主線程中。它的生命周期的方法有onCreate、onStart、onDestory,它還有一些activity的沒有的生命周期方法,onBind和onUnbind

不同的啟動方式,生命周期調用的也不同。

啟動Service的方式有兩種,一種是startService和bindService

a、通過startService

Service會經曆 onCreate 到onStart,然後處于運作狀态,stopService的時候調用onDestroy方法。

這種方式,activity和service是互相獨立的。如果是調用者自己直接退出而沒有調用stopService的話,Service會一直在背景運作

b、通過bindService

Service會運作onCreate,然後是調用onBind, 這個時候調用者和Service綁定在一起。調用者退出了,Service就會調用onUnbind->onDestroyed方法。

這種方式,activity就和service互相捆綁在一起了。所謂綁定在一起就共存亡了。調用者也可以通過調用unbindService方法來停止服務,這時候Service就會調用onUnbind->onDestroyed方法。

Activity為什麼要綁定Service?是因為有些情況下,我們需要調用service裡面的方法。startService的方式我們是調用不到Service裡面的方法的。

如何讓服務長期在背景運作,而activity又可以調用到服務裡面的方法?

先startService 然後bindService進行綁定,這個時候就可以調用服務裡面的方法了。調用完了之後,你就unBindService,這時候退出界面的時候,服務是一直在背景跑的。

預設情況下,服務是運作在主線程中的,在特殊的情況下,我們可以通過AndroidManifest檔案中進行配置android:process="" 這種情況下,服務就在另外一個程序的主線程中。

10. 什麼是IntentService?有何優點?

普通的service ,預設運作在ui main 主線程(ID預設是1)

Sdk給我們提供的友善的,帶有異步處理的service類,

OnHandleIntent() 處理耗時的操作

11、什麼時候需要使用到Service

因為service是具有較高優先級。Android系統會盡量保持擁有service的程序運作,隻要在該service已經被啟動(start)或者用戶端連接配接(bindService)到它。當記憶體不足時,需要保持,擁有service的程序具有較高的優先級。是以我們需要使用到服務Service

在某些情況下,比如服務以及onStart了,那麼此時服務的優先級會稍微的低一些,這時候還是有可能被系統回收,可以通過startForground提高服務的優先級,這個時候,系統就不會回收這個服務了。

因為服務的優先級較高,是以在一些場景中比較适合使用服務,比如:

a、擁有長連接配接QQ

b、定時輪詢、耗時操作

c、服務裡面注冊廣播接收者。有些廣播接收者隻能通過代碼注冊,比如螢幕鎖屏、螢幕解鎖

廣播接收者

12、簡單描述一下廣播接收者

廣播接收者有兩類,一種是系統本身就有的,一種是我們自己寫的廣播接收者。

廣播接收者注冊的方式也有兩種,一種是動态注冊,一種是靜态注冊。

隻能用代碼注冊的廣播,這種廣播産生的頻率是比較高的。比如電量變化的廣播,螢幕解鎖的廣播。電量變化的廣播。

廣播接收者在注冊的時候可以指定優先級,用于提高接收到廣播的順序。

廣播一般是用于跨程序通訊的時候。

13、如何發廣播

廣播分為兩種,一種是有序廣播,一種是無序廣播

有序廣播是按順序被接收的,是可以被攔截和修改裡面的資料的。而無序廣播則沒有接收順序,也無法修改廣播裡面的資料。

攔截廣播可以使用abortBroadcast()将有序廣播給abort掉

資料存儲

14、ContentProvider的使用

把自己的資料通過uri的形式共享出去,這個uri是事先約定好的。

android 系統下 不同程式 資料預設是不能共享通路,通過ContentProvider可以将自己應用的資料提供給别的應用。

我們在寫内容提供者的時候,需要寫一個類繼承ContentProvider,然後實作裡面的增删改查方法

query(Uri, String[], String, String[], String)

insert(Uri, ContentValues)

update(Uri, ContentValues, String, String[])

delete(Uri, String, String[])

15、Android提供的資料存儲方式有哪些(記憶體:效率快,檔案中存儲臨時檔案,開關等)

a、SharedPreferences、sd卡的檔案

b、資料庫sqlite(大量的資料存儲)

c、資料存儲到伺服器上(http協定通路背景接口傳輸上去)

View

16、View的繪制流程,自定義控件的使用

View如何繪制到手機上,一般用onDraw(Canvas canvas)在畫布上(不過在此之前要 onMeasure和onLayout)

onMeasure->onLayout->onDraw

onMeasure:計算寬和高,調用setMeasuredDimension

onLayout: 計算位置

onDraw: 畫在畫布上

自定義控件需要在onMeasure、onLayout、onDraw中的某些方法進行修改,這樣才能保證自定義的控件能夠在正确的位置正确的大小被正确的畫出來。

自定義屬性的使用?

在values的目錄下需要建立一個檔案,叫做attrs.xml 這個檔案是定義屬性規則的。一個屬性的名字、取值類型、取值範圍

在布局檔案中需要加入命名空間,最後在自定義控件中擷取這些值。

17、View的事件傳遞

事件分發dispatchTouchEvent

事件攔截onInterceptTouchEvent{如在桌面中滑動時,傳回true時父攔截事件,點選事件 時,點選時傳回false時,不攔截事件傳遞給子控件就響應了點選事件}

事件響應onTouchEvent

事件傳遞的方向是由父類到子類,事件響應的方向是從子類到父類。

18、ListView的優化

listView是由item充填,每個item都是有getView傳回的(如果有千百個item,就會有千百個inflate會很占記憶體的是以系統就給提供了convertView)

重用了convertView,減少了inflate的次數

使用ViewHolder,減少findViewById的次數,很大程度上的減少了記憶體的消耗。

安卓面試基礎(如會必過)

19、布局的優化(就是提高UI的流程度)

優化布局層次。不要不斷的嵌套LinearLayout ,多使用RelativeLayout 盡可能的減少布局的層次。如:左邊是圖檔,右邊是文字的,可以就使用一個TextView來完成。drawableLeft。

ViewStub(延時加載的view,當使用時才加載)、include(提取一個basePager.xml),listview子元素高度的計算

其他

20、線程間的通訊

Handler是用來進行線程間的通信。

Looper是用來管理所屬線程的消息隊列MessageQueue的

每一個線程都需要有一個looper,每一個looper管理一個MessageQueue

Handler.sendMessage的意思是将某一個message放到MessageQueue中去,looper是個死循環,不斷的讀MessageQueue中的新消息。

要讓looper的死循環運作起來,得調用Looper.loop()方法。

我們通常都會在子線程中,發一個消息到主線程中的messagequeue中去。

21、記憶體洩露的查找

記憶體洩漏本身不會産生什麼危害,真正有危害的是記憶體洩漏的堆積。Android應用記憶體洩漏的的原因有以下幾個:

0、register之後沒有unregister

1查詢資料庫後沒有關閉遊标cursor file沒有close

2 構造Adapter時,沒有使用 convertView 重用

3 Bitmap對象不在使用時調用recycle()釋放記憶體

4 對象被生命周期長的對象引用,如activity被靜态集合引用導緻activity不能釋放

記憶體洩漏如何解決:

生成hprof檔案可以通過adt的工具也可以通過代碼生成。debug的dump方法

22、如何處理大圖檔,圖檔緩存

  1. 有效加載大圖檔,合理設定BitmapFactory.Options的inSampleSize值,減少圖檔記憶體占用;
  2. 僅請求圖檔的大小,inJustDecodeBounds = true,僅請求圖檔大小,而不會加載圖檔到記憶體;
  3. 緩存圖檔,記憶體緩存LruCache

    23、描述一下AIDL的原理

    AIDL的全稱是android interface definition language 接口定義語言。它所做的事情就是跨程序範圍另外一個服務裡面的方法的。跨程序範圍另外一個服務裡面的方法。

    在手機衛士中挂斷電話用到過AIDL。我們要擷取手機系統的電話服務,用到了aidl 它其實工作的原理就是綁定到一個遠端的服務上。然後這個遠端服務會傳回回來一個代理對象。

    這個代理對象裡面的方法,就是我們定義的aidl

    aidl的寫法也非常簡單,主要分兩種。調用系統服務的話,直接找到那個服務的aidl拷貝到我們的項目中就可以了。另外一種是我們自己寫aidl,主要注意的一點是aidl是沒有通路修飾符的。因為aidl本身就是公開的,就是為了給别人調用的,不需要私有的private方法。

    其實呢,在實際的開發過程中,比較少會寫這個aidl,特别是寫app,幾乎用不到 做rom的時候,倒會遇到。那也比較少。但是你得懂它相關的知識是吧。

    在面試的時候,這個也是經常被用的。是以大家要熟悉這個問題的回答方法。

    我以前在中興面試别人的時候,隻要他能回答上幾個關鍵點,我就會讓他過我這關噢。

    1、跨程序 2、aidl在服務端和用戶端都需要有一份 3、通過綁定的方式擷取遠端服務對象的代理IBinder,就可以調用相關的方法。

    跨程序:可用Aidl,廣播,隐式意圖,或者自己寫一個跨程序的一個程序将資料定時存入sd 卡中,然後另一個程序定時從sd卡裡面取出資料。

繼續閱讀