【Android面試題】2

weixin_34279579發表於2017-07-13

理解Activity,View,Window三者關係

這個問題真的很不好回答。所以這裡先來個算是比較恰當的比喻來形容下它們的關係吧。Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示檢視)LayoutInflater像剪刀,Xml配置像窗花圖紙。
1:Activity構造的時候會初始化一個Window,準確的說是PhoneWindow。
2:這個PhoneWindow有一個“ViewRoot”,這個“ViewRoot”是一個View或者說ViewGroup,是最初始的根檢視。
3:“ViewRoot”通過addView方法來一個個的新增View。比如TextView,Button等
4:這些View的事件監聽,是由WindowManagerService來接受訊息,並且回撥Activity函式。比如onClickListener,onKeyDown等。

View的繪製流程

measure過程layout過程draw過程

從此再有不愁自定義View——Android自定義view詳解
android View繪製原始碼分析(上)
android View繪製原始碼分析(下)

Touch事件傳遞機制

public boolean dispatchTouchEvent(MotionEventev);  
//用來分派event
public boolean onInterceptTouchEvent(MotionEventev);
//用來攔截event
public boolean onTouchEvent(MotionEventev);
//用來處理event
其中Activity和View控制元件(TextView)擁有分派和處理事件方法,View容器(LinearLayout)具有分派,攔截,處理事件方法。這裡也有個比喻:領導都會把任務向下分派,一旦下面的人把事情做不好,就不會再把後續的任務交給下面的人來做了,只能自己親自做,如果自己也做不了,就只能告訴上級不能完成任務,上級又會重複他的過程。另外,領導都有權利攔截任務,對下級隱瞞該任務,而直接自己去做,如果做不成,也只能向上級報告不能完成任務。

Handler的原理
IntentService——Handler與Service的結合
Android 開發中利用非同步來優化執行速度和效能
深入理解ThreadLocal(一)

Binder機制原理
為什麼 Android 要採用 Binder 作為 IPC 機制?

Android中的幾種動畫
Android 動畫,看完這些就夠了(上)
Android 動畫,看完這些就夠了(下)

Android中跨程式通訊的幾種方式

1:訪問其他應用程式的Activity
如呼叫系統通話應用

Intent callIntent=new Intent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent);

2:Content Provider
如訪問系統相簿

3:廣播(Broadcast)
如顯示系統時間

4:AIDL服務

請描述一下Activity 生命週期。

如下圖所示。共有七個周期函式,按順序分別是: onCreate(), onStart(), onRestart(), onResume(), onPause(),onStop(), onDestroy()。
onCreate(): 建立Activity時呼叫,設定在該方法中,還以Bundle的形式提供對以前儲存的任何狀態的訪問。
onStart(): Activity變為在螢幕上對使用者可見時呼叫。
onResume(): Activity開始與使用者互動時呼叫(無論是啟動還是重新啟動一個活動,該方法總是被呼叫。
onPause(): Activity被暫停或收回cpu和其他資源時呼叫,該方法使用者保護活動狀態的,也是保護現場。
onStop(): Activity被停止並轉為不可見階段及後續的生命週期事件時呼叫。
onRestart(): Activity被重新啟動時呼叫。該活動仍然在棧中,而不是啟動新的Activity。
1、完整生命週期: 即從一個Activity從出現到消失,對應的週期方法是從onCreate()到onDestroy()。
2、可見生命週期: 當Activity處於可以使用者看見的狀態,但不一定能與使用者互動時,將多次執行從onStart()到onStop()。
3、前景生命週期: 當Activity處於Activity棧最頂端,能夠與其他使用者進行互動時,將多次執行從onResume()到onPause()。

兩個Activity之間跳轉時必然會執行的是哪幾個方法。

兩個Activity之間跳轉必然會執行的是下面幾個方法。
onCreate()//在Activity生命週期開始時呼叫。
onRestoreInstanceState()//用來恢復UI狀態。
onRestart()//當Activity重新啟動時呼叫。
onStart()//當Activity對使用者即將可見時呼叫。
onResume()//當Activity與使用者互動時,繪製介面。
onSaveInstanceState()//即將移出棧頂保留UI狀態時呼叫。
onPause()//暫停當前活動Activity,提交持久資料的改變,停止動畫或其他佔用GPU資源的東西,由於下一個Activity在這個方法返回之前不會resume,所以這個方法的程式碼執行要快。
onStop()//Activity不再可見時呼叫。
onDestroy()//Activity銷燬棧時被呼叫的最後一個方法。

兩個Activity之間怎麼傳遞資料?

可以在Intent物件中利用Extra來傳遞儲存資料。
在Intent的物件請求中,使用putExtra(“鍵值對的名字”,”鍵值對的值”);在另外一個Activity中將Intent中的請求資料取出來: 
Intent intent = getIntent();
String value = intent.getStringExtra(“testIntent”);

Activity怎麼和service繫結,怎麼在activity中啟動自己對應的service?

1、activity能進行繫結得益於Serviece的介面。為了支援Service的繫結,實現onBind方法。
2、Service和Activity的連線可以用ServiceConnection來實現。需要實現一個新的ServiceConnection,重現onServiceConnected和OnServiceDisconnected方法,一旦連線建立,就能得到Service例項的引用。
3、執行繫結,呼叫bindService方法,傳入一個選擇了要繫結的Service的Intent(顯示或隱式)和一個你實現了的ServiceConnection的例項

什麼是Service以及描述下它的生命週期。Service有哪些啟動方法,有什麼區別,怎樣停用Service?

Android Service是執行在後臺的程式碼,不能與使用者互動,可以執行在自己的程式,也可以執行在其他應用程式程式的上下文裡。需要通過某一個Activity或者Context物件來呼叫。Service有兩個啟動方法,分別是Context.startService()和Context.bindService()。如果在Service執行耗時的操作需要啟動一個新執行緒來執行。
Android Service只繼承了onCreate(), onStart(),onDestroy()三個方法,當我們第一次啟動Service時,先後呼叫onCreate(), onStart()這兩個方法,當停止Service時,則執行onDestroy()方法時。如果Service已經啟動了,當我們再次啟動Service時,不會再執行onCreate()方法,而是直接執行onStart()方法。

什麼時候使用Service?

比如播放多媒體的時候,使用者啟動了其他Activity,這個時候程式要在後臺繼續播放,比如檢測SD卡上檔案的變化,再或者在後臺記錄你的地理資訊位置的改變等等。

請描述一下Intent 和 Intent Filter。

 Intent在Android中被翻譯為”意圖”,他是三種應用程式基本元件-Activity,Service和broadcast receiver之間相互啟用的手段。在呼叫Intent名稱時使用ComponentName也就是類的全名時為顯示呼叫。這種方式一般用於應用程式的內部呼叫,因為你不一定會知道別人寫的類的全名。而Intent Filter是指意圖過濾,不出現在程式碼中,而是出現在android Manifest檔案中,以<intent-filter>的形式。(有一個例外是broadcast receiver的intentfilter是使用Context.registerReceiver()來動態設定的,其中intent filter也是在程式碼中建立的)
一個intent有action,data,category等欄位。一個隱式intent為了能夠被某個intent filter接收,必須通過3個[測試](http://lib.csdn.net/base/softwaretest),一個intent為了被某個元件接收,則必須通過它所有的intent filter中的一個。

Intent傳遞資料時,可以傳遞哪些型別資料?

intent間傳送資料一般有兩種常用的方法: 1、extra 2、data。
extra可以用Intent.putExtra放入資料。新啟動的Activity可用Intent.getExtras取出Bundle,然後用Bundles.getLong,getInt,getBoolean,getString等函式來取放進去的值。
Data則是傳輸url。url可以是指我們熟悉的http,ftp等網路地址,也可以指content來指向ContentProvider提供的資源。Intent.setData可以放入資料,Intent.getData可以取出資料。

請描述一下BroadcastReceiver。

Broadcast Receiver用於接收並處理廣播通知(broadcast announcements)。多數的廣播是系統發起的,如地域變換、電量不足、來電簡訊等。程式也可以播放一個廣播。程式可以有任意數量的broadcast receivers來響應它覺得重要的通知。Broadcast receiver可以通過多種方式通知使用者: 啟動activity、使用NotificationManager、開啟背景燈、振動裝置、播放聲音等,最典型的是在狀態列顯示一個圖示,這樣使用者就可以點它開啟看通知內容。通常我們的某個應用或系統本身在某些事件(電池電量不足、來電簡訊)來臨時會廣播一個Intent出去,我們利用註冊一個broadcast
receiver來監聽這些Intent並獲取Intent中的資料。

在manifest和程式碼中如何註冊和使用 broadcast receiver 。

在android的manifest中註冊

<receiver android: name =“Receiver1”>

     <intent-filter>

         <!----和Intent中的action對應--->

         <actionandroid: name=“com.forrest.action.mybroadcast”/>

     </intent-filter>

</receiver>
在程式碼中註冊
1、 IntentFilter filter = new IntentFilter(“com.forrest.action.mybroadcast”);//和廣播中Intent的action對應;
2、 MyBroadcastReceiver br= new MyBroadcastReceiver();
3、 registerReceiver(br, filter);

請介紹下ContentProvider是如何實現資料共享的。

一個程式可以通過實現一個Content provider的抽象介面將自己的資料完全暴露出去,而且Content provider是以類似[資料庫](http://lib.csdn.net/base/mysql)中的表的方式將自己的資料暴露。Content provider儲存和檢索資料,通過它可以讓所有的應用程式訪問到,這也是應用程式之間唯一共享資料的方法。
要想使應用程式的資料公開化,可通過2種方法:建立一個資料自己的Content Provider或者將你的資料新增到一個已經存在的Content Provider中,前提是有相同資料型別並且有寫入Content Provider的許可權,Android提供了Content Resolverr,外界的程式可以通過Content Resolver介面訪問Content Provider提供的資料。

請介紹下Android的資料儲存方式。

Android提供了5中儲存資料的方式,分別是以下幾種
1、使用Shared Preferences儲存資料,用來儲存key-value,pairs格式的資料,它是一個輕量級的鍵值儲存機制,只可以儲存基本資料型別。
2、使用檔案儲存資料,通過FileInputStream和FileOutputStream對檔案進行操作。在Android中,檔案是一個應用程式私有的,一個應用程式無法讀寫其他應用程式的檔案。
3、使用SQLite資料庫儲存資料,Android提供的一個標準資料庫,支援SQL語句。
4、使用Content Provider儲存資料,是所有應用程式之間資料儲存和檢索的一個橋樑,它的作用就是使得各個應用程式之間實現資料共享。它是一個特殊的儲存資料的型別,它提供了一套標準的介面用來獲取資料,運算元據。系統也提供了音訊、視訊、影象和個人資訊等幾個常用的Content Provider。如果你想公開自己的私有資料,可以建立自己的Content Provider類,或者當你對這些資料擁有控制寫入的許可權時,將這些資料新增到Content Provider中實現共享。外部訪問通過Content Resolver去訪問並操作這些被暴露的資料。
5、使用網路儲存資料

談談UI中, Padding和Margin有什麼區別?

 Padding是控制元件的內容相對控制元件的邊緣的邊距,而Margin是控制元件邊緣相對於其他控制元件的邊距。

android本身的一些限制,比如apk包大小限制,讀取大檔案時的時間限

apk包大小限制不好說,有的apk為100M,還是能裝到手機上。一般的apk大小為5~10M左右。讀取大檔案的時間應該是在main執行緒裡面,時間限制為5秒左右。

ListView如何提高其效率?

1、使用分頁載入,不要一次性載入所有資料。
2、複用convertView。在getItemView中,判斷converView是否為空,如果不為空,可複用。
3、非同步載入圖片。Item中如果包含有webimage,那麼最好非同步載入。
4、快速滑動時,不顯示圖片。當快速滑動列表(SCROLL_STATE_FLING),item中的圖片或獲取需要消耗資源的view,可以不顯示出來;而處於其他兩種狀態(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),則將那些view顯示出來

Android程式與Java程式的區別?

2953340-ae90055215d7897b.png
Paste_Image.png

談談對Android NDK的理解。

: android NDK是一套工具,允許Android應用開發者嵌入從C、C++原始碼編譯來的本地機器程式碼到各自的應用軟體包中。
1、 NDK是一系列工具的集合。
NDK提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發者幫助時巨大的。
NDK整合了交叉編輯器,並提供了相應的mk檔案隔離CPU、平臺、API等差異,開發人員只需要簡單修改mk檔案(指出“那些檔案需要編譯”、“編譯特性要求”等),就可以建立出so。NDK可以自動將so和Java應用一起打包,極大的減輕了開發人員的打包工作。
2、NDK提供了一份穩定、功能有限的API標頭檔案宣告。這些API支援的功能非常有限,包含有:C標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、log庫(liblog)。

談談Android的優點和不足之處。

優點如下所示:
1、android是開源、市場佔有率大。
2、android能夠有豐富的硬體選擇。
3、android是一款基於[Linux](http://lib.csdn.net/base/linux)平臺的開源[作業系統](http://lib.csdn.net/base/operatingsystem),從而避免了專利壁壘,是一款完全免費的只能手機平臺。
4、由於android是google開發的,因此能夠無縫結合Google應用。
缺點如下所示:
1、安全與隱私。手機與網際網路緊密聯絡,個人隱私很難得到保守。

Android系統中GC什麼情況下會出現記憶體洩露呢?

導致記憶體洩露主要的原因是,先前申請了記憶體空間而忘記了釋放。如果程式中存在無用物件的引用,那麼這些物件就會駐留記憶體,消耗記憶體,因為無法讓垃圾回收器GC驗證這些物件是否不再需要。如果存在物件的引用,這個物件就被定義為“有效的活動”,同時不會被釋放。要確定物件所佔記憶體將被回收,我們就要確認該物件不會再被使用。典型的做法是把物件資料成員設為null或者從集合中移除該物件。當出現以下情況時,會造成記憶體洩露:
1、 資料庫的cursor沒有關閉。
2、 構造adapter時,沒有使用快取contentview。
3、 Bitmap物件不使用時,採用recycle()釋放記憶體。
4、 Activity中的物件的生命週期大於activity。
除錯方法: DDMS==>HEAPSIZE==>dataobject==>[TotalSize]

Android UI中的View如何重新整理。

 Android中對View的更新方式有很多種,使用時要區分不同的應用場合。要分清的是:多執行緒和雙緩衝。
1、不使用多執行緒和雙緩衝
這種情況最簡單,一般只希望View在發生改變時對UI進行重繪。你只需要Activity中顯式呼叫View物件中的invalidate()方法即可。系統會自動呼叫View的onDraw()方法。
2、使用多執行緒和不使用雙緩衝
這種情況下需要開啟新的執行緒,新開的執行緒就不好訪問View物件了。強行訪問的話會報錯:android.view.ViewRoot$ CalledFromWrongThreadException: only theoriginal thread that created a view hierarchy can touch its views。
這時候你需要建立一個繼承了android.os.handler的子類,並重寫handleMessage方法。Android.os.Handle是能傳送和處理訊息的,你需要在Activity中發出更新UI的訊息,然後再你的Handler(可以使用匿名內部類)中處理訊息(因為匿名內部類可以訪問父類變數,你可以直接呼叫View物件中的invalidate()方法。也就是說:在新執行緒中建立併傳送一個Message,然後在主執行緒中捕獲、處理該訊息。

3、使用多執行緒和雙緩衝
Android的SurfaceView是View的子類,她同時也實現了雙緩衝。你可以定義一個她的子類並實現Surfaceholder.Callback介面。由於SurfaceHolder.Callback介面,新執行緒就不要android.os.Handler幫忙了。SurfaceHolder中lockCanvas()方法可以鎖定畫布,繪製完新的影象後呼叫unlockCanvasand Post解鎖。

相關文章