安卓面試題及答案(三)

7.讓Activity變成一個窗口:


答:Activity屬性設定:有時候會做個應用程序是漂浮在手機主界面的。這個只需要在設置下Activity的主題theme,即在Manifest.xml定義Activity的地方加一句:


android :theme="@android:style/Theme.Dialog"
如果是作半透明的效果:


android:theme="@android:style/Theme.Translucent"


8.Android中常用的五種佈局:


答:LinearLayout線性佈局;AbsoluteLayout絕對佈局;TableLayout表格佈局;RelativeLayout相對佈局;FrameLayout幀佈局;


9.Android的五種數據存儲方式:


答:sharedPreferences;文件;SQLite;contentProvider;網絡


10.請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關係:


答:Handler獲取當前線程中的looper對象,looper用來從存有Message的Message Queue裏取出message,再由Handler進行message的分發和處理。


11.AIDL的全稱是什麼?如何工作?能處理哪些類型的數據?


答:AIDL(AndroidInterface Definition Language)android接口描述語言


12.系統上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?請說明原由:


答:通過直接發送Uri把參數帶過去,或者通過manifest裏的intentfilter裏的data屬性。代碼如下:
    Intent intent = new Intent();


Intent.setAction(“android.intent.action.View”);


Uri uriBrowsers = Uri.parse(“http://www.sina.com.cn”);


Intent.setData(uriBrowsers);


//包名、要打開的activity
    intent.setClassName(“com.android.browser”,”com.android.browser.BrowserActivity”);


startActivity(intent);


13.什麼是ANR,如何避免?


答:ANR的定義:


在android上,如果你的應用程序有一段時間響應不移靈敏,系統會向用戶提示“應用程序無響應”(ANR:application Not Responding)對話框。因此,在程序裏對響應性能的設計很重要,這樣,系統不會顯示ANR給用戶。


如何避免:


首先來研究下爲什麼它會在android的應用程序裏發生和如何最佳構建應用程序來避免ANR.
    android應用程序通常是運行在一個單獨的線程(例如:main)裏,這就意味你的應用程序所做的事情如果在主線程裏佔用了大長時間的話,就會引發ANR對話框,因爲你的應用程序並沒有給自己機會來處理輸入事件或者Intent廣播。


    因此,運行在主線程裏的任何訪求都儘可能少做事情。特別是,activity應該在它的關鍵生命週期方法(onCreate()和onResume())裏儘可能少的去作創建操作。潛在的耗時操作,例如網絡或數據庫操作,或者高耗時的計算如改變位圖尺寸,應該在子線程裏(或者以數據庫操作爲例,通過異步請求的方式)來完成。然而,不是說你的主線程阻塞在那裏等待子線程的完成---也不是調用Thread.wait()或者Thread.sleep()。替代的方法是:主線程應該爲子線程提供一個Handler,以便完成時能夠提交給主線程。以這種方式設計你的應用程序,將能保證你的主線程保持對輸入的響應性並能避免由5秒輸入事件的超時引發的ANR對話框。這種做法應該在其它顯示UI的線程裏效仿,因爲它們都受相同的超時影響。


    IntentReceiver執行時間的特殊限制意味着它應該做:在後臺裏做小的、瑣碎的工作,如保存設定或註冊一個Notification。和在主線程裏調用的其它方法一樣,應用程序應該避免在BroadcastReceiver裏做耗時的操作或計算,但也不是在子線程裏做這些任務(因爲BroadcastReceiver的生命週期短),替代的是,如果響應Intent廣播需要執行一個耗時的動作的話,應用程序應該啓動一個Service。順便提及一句,你也應該避免在Intent Receiver裏啓動一個Activity,因爲它會創建一個新的畫面,並從當前用戶正在運行的程序上搶奪焦點。如果你的應用程序在響應Intent廣播時需要向用戶展示什麼,你應該使用Notification Manager來實現。


    一般來說,在應用程序裏,100到200ms是用戶能感知阻滯的時間閾值,下面總結了一些技巧來避免ANR,並有助於讓你的應用程序看起來有響應性。


    如果你的應用程序爲響應用戶輸入正在後臺工作的話,可以顯示工作的進度(ProgressBar和ProgressDialog對這種情況來說很有用)。特別是遊戲,在子線程裏做移動的計算。如果你的程序有一個耗時的初始化過程的話,考慮可以顯示一個Splash Screen或者快速顯示主畫面並異步來填充這些信息。在這兩種情況下,你都應該顯示正在進行的進度,以免用戶認爲程序被凍結了。


 


14.什麼情況會導致Force Close?如何避免?能否捕獲導致其的異常?


答:如空指針等可以導致ForceClose;可以看Logcat,然後找到對應的程序代碼來解決錯誤。


15.橫豎屏切換時候的activity的生命週期:


答:


1) 新建一個activity,並把各個生命週期打印出來


2) 運行activity,得到如下信息:


onCreate()à


onStart()à


onResume()à


    3)  按ctrl+F12切換成橫屏時


        onSaveInstanceState()à


        onPause()à


        onStop()à


        onDestroy()à


        onCreate()à


        onStart()à


        onRestoreInstanceState()à


        onResume()à


    4)  再按ctrl+f12切換成豎屏時,發現打印了兩次相同的Log


        onSaveInstanceState()à


        onPause()à


        onStop()à


        onDestroyà


        onCreate()à


        onStart()à


        onRestoreInstanceState()à


        onResume()à


 


        onSaveInstanceState()à


        onPause()à


        onStop()à


        onDestroyà


        onCreate()à


        onStart()à


        onRestoreInstanceState()à


        onResume()à


    5)  修改AndroidManifest.xml,把該Activity添加android:configChanges=“orientation”,執行步驟3


        onSaveInstanceState()à


        onPause()à


        onStop()à


        onDestroy()à


        onCreate()à


        onStart()à


        onRestoreInstanceState()à


        onResume()à


    6)  修改AndroidManifest.xml,把該Activity添加android:configChanges=“orientation”,執行步驟4,發現不會再打印相同信息,但多打印了一行onConfigChanged


        onSaveInstanceState()à


        onPause()à


        onStop()à


        onDestroy()à


        onCreate()à


        onStart()à


        onRestoreInstanceState()à


        onResume()à


        onConfigurationChanged()à


    7)  把步驟5的android:configChanges=“orientation”改成


android:configChanges=“orientation|keyboradHidden”,執行步驟3,就只打印onConfigChanged


        onConfigurationChanged()à


    8)  把步驟5的android:configChanges=“orientation”改成


android:configChanges=“orientation|keyboradHidden”,執行步驟4


        onConfigurationChanged()à


        onConfigurationChanged()à


    總結:


1) 不設置activity的android:configChanges時,切屏會重新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次。


2) 設置activity的android:configChanges=“orientation”時, 切屏會重新調用各個生命週期,切橫屏、豎屏時都只會執行一次,但是豎屏最後多打印一條onConfigurationChanged()


3) 設置activity的android:configChanges=“orientation|keyboardHidden”時,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged(),橫屏一次,豎屏兩次


再總結下整個activity的生命週期:


1)  當前activity產生事件彈出Toast和AlertDialog的時候Activity的生命週期不會有改變


2)  Activity運行時按下HOME鍵(跟被完全覆蓋一樣的)


onSavaInstanceStateà


onPauseà


onStopà


 


onRestartà


onStartà


onResumeà


    3)  未被完全覆蓋,只是失去焦點:


        onPauseà


        onResumeà


16.如何將SQLite數據庫(.db文件)與apk文件一起發佈?


答:可以將.db文件複製到Eclipse Android工程中的res aw目錄中。所有在res aw目錄中的文件不會被壓縮,這樣可以直接提取該目錄中的文件。可以將.db文件複製到res aw目錄中


17.如何將打開res aw目錄中的數據庫文件?


答:在Android中不能直接打開res aw目錄中的數據庫文件,而需要在程序第一次啓動時將該文件複製到手機內存或SD卡的某個目錄中,然後再打開該數據庫文件。複製的基本方法是使用getResources().openRawResource方法獲得res aw目錄中資源的 InputStream對象,然後將該InputStream對象中的數據寫入其他的目錄中相應文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法來打開任意目錄中的SQLite數據庫文件。


18.android 中有哪幾種解析xml的類?官方推薦哪種?以及它們的原理和區別:


答:XML解析主要有三種方式,SAX、DOM、PULL。常規在PC上開發我們使用Dom相對輕鬆些,但一些性能敏感的數據庫或手機上還是主要採用SAX方 式,SAX讀取是單向的,優點:不佔內存空間、解析屬性方便,但缺點就是對於套嵌多個分支來說處理不是很方便。而DOM方式會把整個XML文件加載到內存 中去,這裏Android開發網提醒大家該方法在查找方面可以和XPath很好的結合如果數據量不是很大推薦使用,而PULL常常用在J2ME對於節點處 理比較好,類似SAX方式,同樣很節省內存,在J2ME中我們經常使用的KXML庫來解析。


19.DDMS和TraceView的區別?


答:DDMS是一個程序執行查看器,在裏面可以看見線程和堆棧等信息,TraceView是程序性能分析器


20.談談Android的IPC機制:


答:IPC是內部進程通信的簡稱,是共享"命名管道"的資源。Android中的IPC機制是爲了讓Activity和Service之間可以隨時的進行交互,故在Android中該機制,只適用於Activity和Service之間的通信,類似於遠程方法調用,類似於C/S模式的訪問。通過定義AIDL接口文件來定義IPC接口。Servier端實現IPC接口,Client端調用IPC接口本地代理。


21.NDK是什麼:


答:NDK是一系列工具的集合


    NDK提供了一系列的工具,幫助開發者迅速的開發C/C++的動態庫,並能自動將so和java應用打成apk包


    NDK集成了交叉編譯器,並提供了相應的mk文件和隔離cpu,平臺等的差異,開發人員只需簡單的修改mk文件就可以創建出so


22.描述一下android的系統架構:


答:android系統架構分從下往上爲Linux內核層、運行庫、應用程序框架層和應用程序層。


    Linux內核層:負責硬件的驅動程序、網絡、電源、系統安全以及內存管理等功能。


運行庫和androidruntion:運行庫:即c/c++函數庫部分,大多數都是開放源代碼的函數庫,例如webkit,該函數庫負責android網頁瀏覽器的運行;例如標準的c函數庫libc、openssl、sqlite等,當然也包括支持遊戲開發的2dsgl和3dopengles,在多媒體方面有mediaframework框架來支持各種影音和圖形文件的播放與顯示,如mpeg4、h.264、mp3、aac、amr、jpg和png等衆多的多媒體文件格式。Androidruntion負責解釋和執行生成的dalvik格式的字節碼


應用軟件架構:java應用程序開發人員主要是使用該層封裝好的api進行快速開發的。


應用程序層:該層是java的應用程序層,android內置的googlemaps、email、IM、瀏覽器等,都處於該層,java開發人員工發的程序也處於該層,而且和內置的應用程序具有平等的地位,可以調用內置的應用程序,也可以替換內置的應用程序


23.Activity 與 Task的啓動模式有哪些,它們含義具體是什麼?


答:在一個activity中,有多次調用startActivity來啓動另一個activity,要想只生成一個activity實例,可以設置啓動模式。


    一個activity有四種啓動模式:standed,signleTop,singleTask,singleInstance


    Standed:標準模式,一調用startActivity()方法就會產生一個新的實例。


    SingleTop:如果已經有一個實例位於activity棧頂,就不產生新的實例,而只是調用activity中的newInstance()方法。如果不位於棧頂,會產生一個新的實例。


    singleTask:會在一個新的task中產生這個實例,以後每次調用都會使用這個,不會去產生新的實例了。


    SingleInstance:這個和singleTask基本一樣,只有一個區別:在這個模式下的activity實例所處的task中,只能有這個activity實例,不能有其他實例


24.Application類的作用:


答:API裏的第一句是:


Base class for those who need to maintain global application state 


如果想在整個應用中使用全局變量,在java中一般是使用靜態變量,public類型;而在android中如果使用這樣的全局變量就不符合Android的框架架構,但是可以使用一種更優雅的方式就是使用Application context。 
  首先需要重寫Application,主要重寫裏面的onCreate方法,就是創建的時候,初始化變量的值。然後在整個應用中的各個文件中就可以對該變量進行操作了。 
  啓動Application時,系統會創建一個PID,即進程ID,所有的Activity就會在此進程上運行。那麼我們在Application創建的時候初始化全局變量,同一個應用的所有Activity都可以取到這些全局變量的值,換句話說,我們在某一個Activity中改變了這些全局變量的值,那麼在同一個應用的其他Activity中值就會改變


25.說明onSaveInstanceState() 和 onRestoreInstanceState()在什麼時候被調用:


答:Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity時,onSaveInstanceState()纔會被調用。但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。因爲在這種情況下,用戶的行爲決定了不需要保存Activity的狀態。通常onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。


另外,當屏幕的方向發生了改變, Activity會被摧毀並且被重新創建,如果你想在Activity被摧毀前緩存一些數據,並且在Activity被重新創建後恢復緩存的數據。可以重寫Activity的 onSaveInstanceState() 和 onRestoreInstanceState()方法。


26.android的service的生命週期?哪個方法可以多次被調用:


答:1)與採用Context.startService()方法啓動服務有關的生命週期方法


onCreate() -> onStart() -> onDestroy()


onCreate()該方法在服務被創建時調用,該方法只會被調用一次,無論調用多少次startService()或bindService()方法,服務也只被創建一次。
onStart() 只有採用Context.startService()方法啓動服務時纔會回調該方法。該方法在服務開始運行時被調用。多次調用startService()方法儘管不會多次創建服務,但onStart() 方法會被多次調用。
onDestroy()該方法在服務被終止時調用。




2)與採用Context.bindService()方法啓動服務有關的生命週期方法
onCreate() -> onBind() -> onUnbind() -> onDestroy()


onBind()只有採用Context.bindService()方法啓動服務時纔會回調該方法。該方法在調用者與服務綁定時被調用,當調用者與服務已經綁定,多次調用Context.bindService()方法並不會導致該方法被多次調用。
onUnbind()只有採用Context.bindService()方法啓動服務時纔會回調該方法。該方法在調用者與服務解除綁定時被調用。
如果先採用startService()方法啓動服務,然後調用bindService()方法綁定到服務,再調用unbindService()方法解除綁定,最後調用bindService()方法再次綁定到服務,觸發的生命週期方法如下:
onCreate() ->onStart() ->onBind() ->onUnbind()[重載後的方法需返回true] ->onRebind()


27.android的broadcast的生命週期:


答:1)Broadcast receiver生命週期中僅有一個回調方法: 
void onReceive(Context curContext, Intent broadcastMsg) 
當接收器接收到一條broadcast消息,Android就會調用onReceiver(),並傳遞給它一個Intent對象,這個對象攜帶着那條broadcast消息。我們認爲僅當執行這個方式時,Broadcast receiver是活動的;這個方法返回時,它就終止了。這就是Broadcast receiver的生命週期。 




2)由於Broadcast receiver的生命週期很短,一個帶有活動的Broadcast receiver的進程是受保護的,以避免被幹掉;但是別忘了有一點,Android會在任意時刻幹掉那些攜帶不再活動的組件的進程,所以很可能會造成這個問題。 




3)解決上述問題的方案採用一個Service來完成這項工作,Android會認爲那個進程中(Service所在的進程)仍然有在活動的組件。 


28.android view,surfaceview,glsurfaceview的區別:


答:SurfaceView是從View基類中派生出來的顯示類,直接子類有GLSurfaceView和VideoView,可以看出GL和視頻播放以及Camera攝像頭一般均使用SurfaceView
SurfaceView和View最本質的區別在於,surfaceView是在一個新起的單獨線程中可以重新繪製畫面而View必須在UI的主線程中更新畫面。 
那麼在UI的主線程中更新畫面 可能會引發問題,比如你更新畫面的時間過長,那麼你的主UI線程會被你正在畫的函數阻塞。那麼將無法響應按鍵,觸屏等消息。 
當使用surfaceView 由於是在新的線程中更新畫面所以不會阻塞你的UI主線程。但這也帶來了另外一個問題,就是事件同步。比如你觸屏了一下,你需要surfaceView中thread處理,一般就需要有一個event queue的設計來保存touch event,這會稍稍複雜一點,因爲涉及到線程同步。 


所以基於以上,根據遊戲特點,一般分成兩類。 


1)被動更新畫面的。比如棋類,這種用view就好了。因爲畫面的更新是依賴於 onTouch 來更新,可以直接使用 invalidate。 因爲這種情況下,這一次Touch和下一次的Touch需要的時間比較長些,不會產生影響。 


2)主動更新。比如一個人在一直跑動。這就需要一個單獨的thread不停的重繪人的狀態,避免阻塞main UI thread。所以顯然view不合適,需要surfaceView來控制。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章