Android面試題集

轉載:http://blog.csdn.net/dd864140130/article/details/57408502

基礎

談談Activity的生命週期

這裏寫圖片描述

介紹不一樣場景下Activity生命週期的變化過程

  • 啓動Activity: onCreate()—>onStart()—>onResume(),Activity進入運行狀態。
  • Activity退居後臺: 當前Activity轉到新的Activity界面或按Home鍵回到主屏: onPause()—>onStop(),進入停滯狀態。
  • Activity返回前臺: onRestart()—>onStart()—>onResume(),再次回到運行狀態。
  • Activity退居後臺,且系統內存不足, 系統會殺死這個後臺狀態的Activity,若再次回到這個Activity,則會走onCreate()–>onStart()—>onResume()
  • 鎖定屏與解鎖屏幕 只會調用onPause(),而不會調用onStop方法,開屏後則調用onResume()

Activity銷燬但Task若是沒有銷燬掉,當Activity重啓時這個AsyncTask該如何解決?

仍是屏幕旋轉這個例子,在重建Activity的時候,會回調 
Activity.onRetainNonConfigurationInstance()從新傳遞一個新的對象給AsyncTask,完成引用的更新html

Asynctask爲何要設置爲只可以一次任務

考慮到線程安全問題java

若Activity已經銷燬,此時AsynTask執行完並返回結果,會報異常麼?

當一個App旋轉時,整個Activity會被銷燬和重建。當Activity重啓時,AsyncTask中對該Activity的引用是無效的,所以onPostExecute()就不會起做用,若AsynTask正在執行,折會報 view not attached to window manager 異常mysql

一樣也是生命週期的問題,在 Activity 的onDestory()方法中調用Asyntask.cancal方法,讓兩者的生命週期同步linux

內存不足時,系統會殺死後臺的Activity,若是須要進行一些臨時狀態的保存,在哪一個方法進行

Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並非生命週期方法,不一樣於 onCreate()、onPause()等生命週期方法,它們並不必定會被觸發。當應用遇到意外狀況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity,onSaveInstanceState() 會被調用。可是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。除非該activity是被用戶主動銷燬的,一般onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。android

介紹Activity 四中launchMode:

  • standard
  • singleTop
  • singleTask
  • singleInstance

咱們能夠在AndroidManifest.xml配置的android:launchMode屬性爲以上四種之一。 
1. standard standard模式是默認的啓動模式,不用爲配置android:launchMode屬性便可,固然也能夠指定值爲standard。standard啓動模式,無論有沒有已存在的實例,都生成新的實例。 
2. singleTop 咱們在上面的基礎上爲指定屬性android:launchMode=」singleTop」,系統就會按照singleTop啓動模式處理跳轉行爲。跳轉時系統會先在棧結構中尋找是否有一個Activity實例正位於棧頂,若是有則再也不生成新的,而是直接使用。若是系統發現存在有Activity實例,但不是位於棧頂,從新生成一個實例。 這就是singleTop啓動模式,若是發現有對應的Activity實例正位於棧頂,則重複利用,再也不生成新的實例。 
3. singleTask 若是發現有對應的Activity實例,則使此Activity實例之上的其餘Activity實例通通出棧,使此Activity實例成爲棧頂對象,顯示到幕前。 
4. singleInstance 這種啓動模式比較特殊,由於它會啓用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證再也不有其餘Activity實例進入。git

LaunchMode使用場景

  1. singleTop適合接收通知啓動的內容顯示頁面。 
    例如,某個新聞客戶端的新聞內容頁面,若是收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。
  2. singleTask適合做爲程序入口點。 
    例如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent,而且會清空主界面上面的其餘頁面。
  3. singleInstance應用場景: 
    鬧鈴的響鈴界面。 你之前設置了一個鬧鈴:上午6點。在上午5點58分,你啓動了鬧鈴設置界面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天;在6點時,鬧鈴響了,而且彈出了一個對話框形式的 Activity(名爲 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵,回到的是微信的聊天界面,這是由於 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 所以退出以後這個 Task 的棧空了。若是是以 SingleTask 打開 AlarmAlertActivity,那麼當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設置界面。

如何把一個應用設置爲系統應用

  1. Android設置是Debug版本,且root,直接將該apk用adb工具push到system/app或system/priv-app
  2. 若是是非root設備,須要編譯後燒寫鏡像
  3. 有些權限(如WRITE_SECURE_SETTINGS)不開放給第三方應用,只能在對應設備源碼總編譯而後做爲系統app使用

Activity,Window,View三者的聯繫和區別?

Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。github

Activity啓動Service的兩種方式

  1. startService:生命週期和調用者不一樣.啓動後若調用者未調用stopService而直接退出,Service仍會運行
  2. bindService:生命週期與調用者綁定,調用者一旦退出,Service就會調用unBind->onDestory

Android兩個應用能在同一個任務棧嗎?

棧通常以包名命名,兩個應用的簽名和udid要相同web

Fragment是什麼?你曾經遇到哪些有關Fragment的問題?

Fragment能夠做爲Activity界面的一部分組成出現.一個Activity中能夠同時出現多個Fragment,並一個Fragment也能夠在多個Activity中使用.算法

在Activity中能夠添加,刪除,替換Fragment.Fragment能夠響應本身的輸入時間,而且有本身的生命週期,但其生命週期收Activity影響.sql

Fragment生命週期

這裏寫圖片描述

如何實現Activity窗口快速變暗

* @param from\>=0&&from\<=1.0f * @param to\>=0&&to\<=1.0f * * */ private void dimBackground(final float from, final float to) { final Window window = getWindow(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to); valueAnimator.setDuration(500); valueAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { WindowManager.LayoutParams params = window.getAttributes(); params.alpha = (Float) animation.getAnimatedValue(); window.setAttributes(params); } }); valueAnimator.start(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Fragment重疊問題

是否使用過本地廣播,和全局廣播有什麼區別?

本地廣播在本應用範圍內傳播,不用擔憂隱私數據泄露,不用擔憂別的應用僞造廣播.相比全局廣播,本地廣播更高效.

註冊廣播的幾種方法?

1.靜態註冊:在清單文件中註冊, 常見的有監聽設備啓動,常駐註冊不會隨程序生命週期改變 
2.動態註冊:在代碼中註冊,隨着程序的結束,也就中止接受廣播了

補充一點:有些廣播只能經過動態方式註冊,好比時間變化事件、屏幕亮滅事件、電量變動事件,由於這些事件觸發頻率一般很高,若是容許後臺監聽,會致使進程頻繁建立和銷燬,從而影響系統總體性能

爲何Android引入廣播機制?

a:從MVC的角度考慮(應用程序內) 其實回答這個問題的時候還能夠這樣問,android爲何要有那4大組件,如今的移動開發模型基本上也是照搬的web那一套MVC架構,只不過是改了點嫁妝而已。android的四大組件本質上就是爲了實現移動或者說嵌入式設備上的MVC架構,它們之間有時候是一種相互依存的關係,有時候又是一種補充關係,引入廣播機制能夠方便幾大組件的信息和數據交互。 
b:程序間互通消息(例如在本身的應用程序內監聽系統來電) 
c:效率上(參考UDP的廣播協議在局域網的方便性) 
d:設計模式上(反轉控制的一種應用,相似監聽者模式)

BroadCastReceiver的安全性問題

具體參見:[http://blog.csdn.net/t12x3456/article/details/9256609]

瞭解IntentServices嗎?

IntentService是Service的子類,是一個異步的,會自動中止的服務,很好解決了傳統的Service中處理完耗時操做忘記中止並銷燬Service的問題

生成一個默認的且與線程相互獨立的工做線程執行全部發送到onStartCommand()方法的Intent,能夠在onHandleIntent()中處理.

串行隊列,每次只運行一個任務,不存在線程安全問題,全部任務執行完後自動中止服務,不須要本身手動調用stopSelf()來中止.

Service的onCreate運行在哪一個線程中?

UI線程

提高Service進程優先級

在AndroidManifest.xml文件中對於intent-filter能夠經過android:priority = 「1000」這個屬性設置最高優先級,1000是最高值,若是數字越小則優先級越低,同時適用於廣播。

介紹Android下的數據存儲方式

  1. SharedPreference
  2. 內部存儲
  3. 外部存儲
  4. SQLite
  5. 網絡存儲

ContentProvider是如何實現數據共享

當一個應用程序須要把本身的數據暴露給其餘程序使用時,該就用程序就可經過提供ContentProvider來實現;其餘應用程序就可經過ContentResolver來操做ContentProvider暴露的數據。 一旦某個應用程序經過ContentProvider暴露了本身的數據操做接口,那麼無論該應用程序是否啓動,其餘應用程序均可以經過該接口來操做該應用程序的內部數據,包括增長數據、刪除數據、修改數據、查詢數據等。

ContentProvider以某種Uri的形式對外提供數據,容許其餘應用訪問或修改數據;其餘應用程序使用ContentResolver根據Uri去訪問操做指定數據。 步驟: 
1. 定義本身的ContentProvider類,該類須要繼承Android提供的ContentProvider基類。 
2. 在AndroidManifest.xml文件中註冊個ContentProvider,註冊ContenProvider時須要爲它綁定一個URL。 例: android:authorities=」com.myit.providers.MyProvider」 /> 說明:authorities就至關於爲該ContentProvider指定URL。 註冊後,其餘應用程序就能夠經過該Uri來訪問MyProvider所暴露的數據了。 
3. 接下來,使用ContentResolver操做數據,Context提供了以下方法來獲取ContentResolver對象。 通常來講,ContentProvider是單例模式,當多個應用程序經過ContentResolver來操做 ContentProvider提供的數據時,ContentResolver調用的數據操做將會委託給同一個ContentProvider處理。 使用ContentResolver操做數據只需兩步: 一、調用Activity的ContentResolver獲取ContentResolver對象。 二、根據須要調用ContentResolver的insert()、delete()、update()和query()方法操做數據便可

ContentProvider和sql的區別

ContentProvider的主要仍是用於數據共享,其能夠對Sqlite,SharePreferences,File等進行數據操做用來共享數據。而sql的能夠理解爲數據庫的一門語言,可使用它完成CRUD等一系列的操做

數據存儲相關

  • 文件存儲: 經過Java.io.FileInputStream和java.io.FileOutputStream這兩個類來實現對文件的讀寫,java.io.File類則用來構造一個具體指向某個文件或者文件夾的對象。

  • SharedPreferences: SharedPreferences是一種輕量級的數據存儲機制,他將一些簡單的數據類型的數據,包括boolean類型,int類型,float類型,long類型以及String類型的數據,以鍵值對的形式存儲在應用程序的私有Preferences目錄(/data/data/<包名>/shared_prefs/)中,這種Preferences機制普遍應用於存儲應用程序中的配置信息。

  • SQLite數據庫: 當應用程序須要處理的數據量比較大時,爲了更加合理地存儲、管理、查詢數據,咱們每每使用關係數據庫來存儲數據。Android系統的不少用戶數據,如聯繫人信息,通話記錄,短信息等,都是存儲在SQLite數據庫當中的,因此利用操做SQLite數據庫的API能夠一樣方便的訪問和修改這些數據。

  • ContentProvider: 主要用於在不一樣的應用程序之間實現數據共享的功能,不一樣於sharepreference和文件存儲中的兩種全局可讀寫操做模式,內容提供其能夠選擇只對哪一部分數據進行共享,從而保證咱們程序中的隱私數據不會有泄漏的風險

如何導入外部數據庫?

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

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

一條最長的短信息約佔多少byte?

中文70(包括標點),英文160,160個字節。

Context與ApplicationContext的區別,

Application的Context是一個全局靜態變量,SDK的說明是隻有當你引用這個context的生命週期超過了當前activity的生命週期,而和整個應用的生命週期掛鉤時,纔去使用這個application的context。 
在android中context能夠做不少操做,可是最主要的功能是加載和訪問資源。在android中有兩種context,一種是 application context,一種是activity context,一般咱們在各類類和方法間傳遞的是activity context。

什麼是aar?aar是jar有什麼區別?

「aar」包是 Android 的類庫項目的二進制發行包。 
文件擴展名是.aar,maven 項目類型應該也是aar,但文件自己是帶有如下各項的 zip 文件: 
/AndroidManifest.xml (mandatory) 
/classes.jar (mandatory) 
/res/ (mandatory) 
/R.txt (mandatory) 
/assets/ (optional) 
/libs/*.jar (optional) 
/jni//*.so (optional) 
/proguard.txt (optional) 
/lint.jar (optional) 
這些條目是直接位於 zip 文件根目錄的。 其中R.txt 文件是aapt帶參數–output-text-symbols的輸出結果。 
jar打包不能包含資源文件,好比一些drawable文件、xml資源文件之類的,aar能夠。

SQLite支持事務嗎?添加刪除如何提升性能?

SQLite做爲輕量級的數據庫,比MySQL還小,但支持SQL語句查詢,提升性能能夠考慮經過原始通過優化的SQL查詢語句方式處理

SQLite優化

參考:[http://www.cnblogs.com/devinzhang/archive/2012/01/16/2323949.html]

如何將SQLite數據庫(dictionary.db文件)與apk文件一塊兒發佈?

能夠將dictionary.db文件複製到Eclipse Android工程中的res aw目錄中。全部在res aw目錄中的文件不會被壓縮,這樣能夠直接提取該目錄中的文件。能夠將dictionary.db文件複製到res aw目錄中

Webview中的漏洞

[http://jiajixin.cn/2014/09/16/webview-js-safety/]

Service和Activity通訊

  1. 經過Binder
  2. 經過broadcast

如何保證Service在後臺不被kill

  1. Service設置成START_STICKY kill 後會被重啓(等待5秒左右),重傳Intent,保持與重啓前同樣

  2. 經過 startForeground將進程設置爲前臺進程, 作前臺服務,優先級和前臺應用一個級別​,除非在系統內存很是缺,不然此進程不會被 kill

  3. 雙進程Service: 讓2個進程互相保護**,其中一個Service被清理後,另外沒被清理的進程能夠當即重啓進程

  4. QQ黑科技: 在應用退到後臺後,另起一個只有 1 像素的頁面停留在桌面上,讓本身保持前臺狀態,保護本身不被後臺清理工具殺死

  5. 在已經root的設備下,修改相應的權限文件,將App假裝成系統級的應用 Android4.0系列的一個漏洞,已經確承認行

  6. 用C編寫守護進程(即子進程) : Android系統中當前進程(Process)fork出來的子進程,被系統認爲是兩個不一樣的進程。當父進程被殺死的時候,子進程仍然能夠存活,並不受影響。鑑於目前提到的在Android->- Service層作雙守護都會失敗,咱們能夠fork出c進程,多進程守護。死循環在那檢查是否還存在,具體的思路以下(Android5.0以上的版本不可行)

  7. 用C編寫守護進程(即子進程),守護進程作的事情就是循環檢查目標進程是否存在,不存在則啓動它。
  8. 在NDK環境中將1中編寫的C代碼編譯打包成可執行文件(BUILD_EXECUTABLE)。主進程啓動時將守護進程放入私有目錄下,賦予可執行權限,啓動它便可。

  9. 聯繫廠商,加入白名單

談談你對Android中Context的理解

參考:[http://blog.csdn.net/qinjuning/article/details/7310620]

RemoteView的應用

widget和Notification中

Android中如何得到手機的惟一標示.

1 首先嚐試讀取IMEI、Mac地址、CPU號等物理信息(有很多工具能夠修改IMEI); 
2 若是均失敗,能夠本身生成UUID而後保存到文件(文件也可能被篡改或刪除)

參考:[http://blog.csdn.net/xushuaic/article/details/25077179]

Android應用中驗證碼登陸都有哪些實現方案

驗證碼應該只有兩種獲取方式: 從服務器端獲取圖片, 經過短信服務,將驗證碼發送給客戶端這兩種

爲何要設計Bundle而不是直接使用Map?

Map裏實現了Serializable接口,而在Bundle實現了Parcelable的接口 
Bundle 父類 BaseBundle內部確實有個 ArrayMap

Android中XML解析方式的比較急優缺點

DOM,SAX,Pull解析。 
SAX解析器的優勢是解析速度快,佔用內存少; 
DOM在內存中以樹形結構存放,所以檢索和更新效率會更高。可是對於特別大的文檔,解析和加載整個文檔將會很耗資源,不適合移動端; 
PULL解析器的運行方式和SAX相似,都是基於事件的模式,PULL解析器小巧輕便,解析速度快,簡單易用,很是適合在Android移動設備中使用,Android系統內部在解析各類XML時也是用PULL解析器。


佈局相關

LinearLayout和RelativeLayout性能對比

1 RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,也會調用子View2次onMeasure 
2 RelativeLayout的子View若是高度和RelativeLayout不一樣,則會引起效率問題,當子View很複雜時,這個問題會更加嚴重。若是能夠,儘可能使用padding代替margin。 
3 在不影響層級深度的狀況下,使用LinearLayout和FrameLayout而不是RelativeLayout。 
最後再思考一下文章開頭那個矛盾的問題,爲何Google給開發者默認新建了個RelativeLayout,而本身卻在DecorView中用了個LinearLayout。由於DecorView的層級深度是已知並且固定的,上面一個標題欄,下面一個內容欄。採用RelativeLayout並不會下降層級深度,因此此時在根節點上用LinearLayout是效率最高的。而之因此給開發者默認新建了個RelativeLayout是但願開發者能採用儘可能少的View層級來表達佈局以實現性能最優,由於複雜的View嵌套對性能的影響會更大一些。

屏幕適配相關

dp, dip, dpi, px, sp是什麼意思以及他們的換算公式?layout-sw400dp, layout-h400dp分別表明什麼意思

佈局優化

  • 避免OverDraw過渡繪製
  • 優化佈局層級
  • 避免嵌套過多無用佈局
  • 當咱們在畫布局的時候,若是能實現相同的功能,優先考慮相對佈局,而後在考慮別的佈局,不要用絕對佈局。
  • 使用<include />標籤把複雜的界面須要抽取出來
  • 使用<merge />標籤,由於它在優化UI結構時起到很重要的做用。目的是經過刪減多餘或者額外的層級,從而優化整個Android Layout的結構。核心功能就是減小冗餘的層次從而達到優化UI的目的!
  • ViewStub 是一個隱藏的,不佔用內存空間的視圖對象,它能夠在運行時延遲加載佈局資源文件。

mipmap文件夾和drawable文件夾的區別

它只是用來放啓動圖標的,好處就是,你只用放一個mipmap圖標,它就會給你各類版本(好比平板,手機)的apk自動生成相應分辨率的圖標,以節約空間。

ListView卡頓的緣由以及優化策略

  • 重用converView: 經過複用converview來減小沒必要要的view的建立,另外Infalte操做會把xml文件實例化成相應的View實例,屬於IO操做,是耗時操做。

  • 減小findViewById()操做: 將xml文件中的元素封裝成viewholder靜態類,經過converview的setTag和getTag方法將view與相應的holder對象綁定在一塊兒,避免沒必要要的findviewbyid操做

  • 避免在 getView 方法中作耗時的操做: 例如加載本地 Image 須要載入內存以及解析 Bitmap ,都是比較耗時的操做,若是用戶快速滑動listview,會由於getview邏輯過於複雜耗時而形成滑動卡頓現象。用戶滑動時候不要加載圖片,待滑動完成再加載,可使用這個第三方庫glide

  • Item的佈局層次結構儘可能簡單,避免佈局太深或者沒必要要的重繪

  • 儘可能能保證 Adapter 的 hasStableIds() 返回 true 這樣在 notifyDataSetChanged() 的時候,若是item內容並無變化,ListView 將不會從新繪製這個 View,達到優化的目的

  • 在一些場景中,ScollView內會包含多個ListView,能夠把listview的高度寫死固定下來。 因爲ScollView在快速滑動過程當中須要大量計算每個listview的高度,阻塞了UI線程致使卡頓現象出現,若是咱們每個item的高度都是均勻的,能夠經過計算把listview的高度肯定下來,避免卡頓現象出現

  • 使用 RecycleView 代替listview: 每一個item內容的變更,listview都須要去調用notifyDataSetChanged來更新所有的item,太浪費性能了。RecycleView能夠實現當個item的局部刷新,而且引入了增長和刪除的動態效果,在性能上和定製上都有很大的改善

  • ListView 中元素避免半透明: 半透明繪製須要大量乘法計算,在滑動時不停重繪會形成大量的計算,在比較差的機子上會比較卡。 在設計上能不半透明就不不半透明。實在要弄就把在滑動的時候把半透明設置成不透明,滑動完再從新設置成半透明。

  • 儘可能開啓硬件加速: 硬件加速提高巨大,避免使用一些不支持的函數致使含淚關閉某個地方的硬件加速。固然這一條不僅是對 ListView。

如何實現一個局部更新的ListView

如何實現ListView多種佈局

ViewHolder爲何要被聲明成靜態內部類

這個是考靜態內部類和非靜態內部類的主要區別之一。非靜態內部類會隱式持有外部類的引用,就像你們常常將自定義的adapter在Activity類裏,而後在adapter類裏面是能夠隨意調用外部activity的方法的。當你將內部類定義爲static時,你就調用不了外部類的實例方法了,由於這時候靜態內部類是不持有外部類的引用的。聲明ViewHolder靜態內部類,能夠將ViewHolder和外部類解引用。你們會說通常ViewHolder都很簡單,不定義爲static也沒事吧。確實如此,可是若是你將它定義爲static的,說明你懂這些含義。萬一有一天你在這個ViewHolder加入一些複雜邏輯,作了一些耗時工做,那麼若是ViewHolder是非靜態內部類的話,就很容易出現內存泄露。若是是靜態的話,你就不能直接引用外部類,迫使你關注如何避免相互引用。 因此將 ViewHolder內部類 定義爲靜態的,是一種好習慣


進程,線程

有哪些進程通訊的方式?

  1. Intent
  2. Binder(AIDL
  3. Messenger
  4. BroadcastReceiver

AIDL是什麼?

AIDL全程是Android Interface Definition Language,用於生成兩個進程之間通訊(IPC)的代碼.

AIDL 體現了哪些設計思想

代理

Binder機制

不少人吧Binder的原理解釋的很複雜,讓人看着就頭大,可是熟悉Linux開發的小夥伴能夠一下想到Binder驅動本質就是文件,實現採用了代理而已.具體看下圖: 
這裏寫圖片描述

簡單的說說Handler機制

  • Handler經過調用sendmessage方法把消息放在消息隊列MessageQueue中,Looper負責把消息從消息隊列中取出來,從新再交給Handler進行處理,三者造成一個循環
  • 經過構建一個消息隊列,把全部的Message進行統一的管理,當Message不用了,並不做爲垃圾回收,而是放入消息隊列中,供下次handler建立消息時候使用,提升了消息對象的複用,減小系統垃圾回收的次數
  • 每個線程,都會單獨對應的一個looper,這個looper經過ThreadLocal來建立,保證每一個線程只建立一個looper,looper初始化後就會調用looper.loop建立一個MessageQueue,這個方法在UI線程初始化的時候就會完成,咱們不須要手動建立

動畫相關

Android中的動畫有哪些?

  • 逐幀動畫(Drawable Animation): 加載一系列Drawable資源來建立動畫,簡單來講就是播放一系列的圖片來實現動畫效果,能夠自定義每張圖片的持續時間

  • 補間動畫(Tween Animation): Tween能夠對View對象實現一系列簡單的動畫效果,好比位移,縮放,旋轉,透明度等等。可是它並不會改變View屬性的值,只是改變了View的繪製的位置,好比,一個按鈕在動畫事後,不在原來的位置,可是觸發點擊事件的仍然是原來的座標。

  • 屬性動畫(Property Animation): 動畫的對象除了傳統的View對象,還能夠是Object對象,動畫結束後,Object對象的屬性值被實實在在的改變了

Android動畫原理

Animation框架定義了透明度,旋轉,縮放和位移幾種常見的動畫,並且控制的是整個View,實現原理是每次繪製視圖時View所在的ViewGroup中的drawChild函數獲取該View的Animation的Transformation值,而後調用canvas.concat(transformToApply.getMatrix()),經過矩陣運算完成動畫幀,若是動畫沒有完成,繼續調用invalidate()函數,啓動下次繪製來驅動動畫,動畫過程當中的幀之間間隙時間是繪製函數所消耗的時間,可能會致使動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,並不能相應事件

Android屬性動畫特性

若是你的需求中只須要對View進行移動、縮放、旋轉和淡入淡出操做,那麼補間動畫確實已經足夠健全了。可是很顯然,這些功能是不足以覆蓋全部的場景的,一旦咱們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操做,那麼補間動畫就不能再幫咱們忙了,也就是說它在功能和可擴展方面都有至關大的侷限性,那麼下面咱們就來看看補間動畫所不能勝任的場景。 
注意上面我在介紹補間動畫的時候都有使用「對View進行操做」這樣的描述,沒錯,補間動畫是隻可以做用在View上的。也就是說,咱們能夠對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操做,可是若是咱們想要對一個非View的對象進行動畫操做,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會須要對一個非View的對象進行動畫操做呢?這裏我舉一個簡單的例子,好比說咱們有一個自定義的View,在這個View當中有一個Point對象用於管理座標,而後在onDraw()方法當中就是根據這個Point對象的座標值來進行繪製的。也就是說,若是咱們能夠對Point對象進行動畫操做,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具有這個功能的,這是它的第一個缺陷。 
而後補間動畫還有一個缺陷,就是它只可以實現移動、縮放、旋轉和淡入淡出這四種動畫操做,那若是咱們但願能夠對View的背景色進行動態地改變呢?很遺憾,咱們只能靠本身去實現了。說白了,以前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。 
最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?好比說,如今屏幕的左上角有一個按鈕,而後咱們經過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,由於實際上這個按鈕仍是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪製到了屏幕的右下角而已。


View繪製相關

SurfaceView和View的區別

SurfaceView中採用了雙緩存技術,在單獨的線程中更新界面 
View在UI線程中更新界面

介紹下自定義view的基本流程

  1. 明確需求,肯定你想實現的效果
  2. 肯定是使用組合控件的形式仍是全新自定義的形式,組合控件即便用多個系統控件來合成一個新控件,你好比titilebar,這種形式相對簡單,參考
  3. 若是是徹底自定義一個view的話,你首先須要考慮繼承哪一個類,是View呢,仍是ImageView等子類。
  4. 根據須要去複寫View#onDraw、View#onMeasure、View#onLayout方法
  5. 根據須要去複寫dispatchTouchEvent、onTouchEvent方法
  6. 根據須要爲你的自定義view提供自定義屬性,即編寫attr.xml,而後在代碼中經過TypedArray等類獲取到自定義屬性值 7.須要處理滑動衝突、像素轉換等問題

談談View的繪製流程

這裏寫圖片描述 
measure()方法,layout(),draw()三個方法主要存放了一些標識符,來判斷每一個View是否須要再從新測量,佈局或者繪製,主要的繪製過程仍是在onMeasure,onLayout,onDraw這個三個方法中

1.onMesarue() 爲整個View樹計算實際的大小,即設置實際的高(對應屬性:mMeasuredHeight)和寬(對應屬性: mMeasureWidth),每一個View的控件的實際寬高都是由父視圖和自己視圖決定的。

2.onLayout() 爲將整個根據子視圖的大小以及佈局參數將View樹放到合適的位置上。

3. onDraw() 開始繪製圖像,繪製的流程以下

  1. 首先繪製該View的背景
  2. 調用onDraw()方法繪製視圖自己 (每一個View都須要重載該方法,ViewGroup不須要實現該方法)
  3. 若是該View是ViewGroup,調用dispatchDraw ()方法繪製子視圖
  4. 繪製滾動條

自定義View執行invalidate()方法,爲何有時候不會回調onDraw()

  1. 自定義一個view時,重寫onDraw。調用view.invalidate(),會觸發onDraw和computeScroll()。前提是該view被附加在當前窗口. 
    view.postInvalidate(); //是在非UI線程上調用的

  2. 自定義一個ViewGroup,重寫onDraw。onDraw可能不會被調用,緣由是須要先設置一個背景(顏色或圖)。表示這個group有東西須要繪製了,纔會觸發draw,以後是onDraw。所以,通常直接重寫dispatchDraw來繪製viewGroup.自定義一個ViewGroup,dispatchDraw會調用drawChild.

如何實現一個字體的描邊與陰影效果


事件傳遞機制

談談touch事件的傳遞流程

這裏寫圖片描述 
1. 全部Touch事件都被封裝成了MotionEvent對象,包括Touch的位置、時間、歷史記錄以及第幾個手指(多指觸摸)等。 
2. 事件類型分爲ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每一個事件都是以ACTION_DOWN開始ACTION_UP結束。 
3. 對事件的處理包括三類,分別爲傳遞——dispatchTouchEvent()函數、攔截——onInterceptTouchEvent()函數、消費——onTouchEvent()函數和OnTouchListener()

簡單來講:

  1. 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被中止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View能夠經過onTouchEvent()對事件進行處理。

  2. 事件由父View(ViewGroup)傳遞給子View,ViewGroup能夠經過onInterceptTouchEvent()對事件作攔截,中止其往下傳遞。

  3. 若是事件從上往下傳遞過程當中一直沒有被中止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)能夠進行消費,若是仍是沒有被消費的話,最後會到Activity的onTouchEvent()函數。

  4. 若是View沒有對ACTION_DOWN進行消費,以後的其餘事件不會傳遞過來。

  5. OnTouchListener優先於onTouchEvent()對事件進行消費。 
    上面的消費即表示相應函數返回值爲true。

View中setOnTouchListener中的onTouch,onTouchEvent,onClick的執行順序

onTouch優於onTouchEvent,onTouchEvent優於onClick

Android下滑衝突的常看法決思路

相關的滑動組件 重寫onInterceptTouchEvent,而後判斷根據xy值,來決定是否要攔截當前操做


高效使用Bitmap

談談你對Bitmap的理解,以及何時該bitmap.recycle()

Bitmap是android中常用的一個類,它表明了一個圖片資源。 Bitmap消耗內存很嚴重,若是不注意優化代碼,常常會出現OOM問題,優化方式一般有這麼幾種: 1. 使用緩存; 2. 壓縮圖片; 3. 及時回收;

至於何時須要手動調用recycle,這就看具體場景了,原則是當咱們再也不使用Bitmap時,須要回收。另外,咱們須要注意,2.3以前Bitmap對象與像素數據是分開存放的,Bitmap對象存在Java Heap中而像素數據存放在Native Memory中,這時頗有必要調用recycle回收內存。可是2.3以後,Bitmap對象和像素數據都是存在Heap中,GC能夠回收其內存。


反射相關

何時會用到反射?

JAVA反射機制是在#運行時#,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。 Java反射機制主要提供瞭如下功能: a)在運行時判斷任意一個對象所屬的類; b)在運行時構造任意一個類的對象; c)在運行時判斷任意一個類所具備的成員變量和方法; d)在運行時調用任意一個對象的方法;生成動態代理。

你曾經利用反射作過什麼?


JNI系列

NDK是什麼?

NDK是一些列工具的集合, 
NDK提供了一系列的工具,幫助開發者迅速的開發C/C++的動態庫,並能自動將so和java 應用打成apk包。 
NDK集成了交叉編譯器,並提供了相應的mk文件和隔離cpu、平臺等的差別,開發人員只需簡單的修改mk文件就能夠建立出so

Android ndk主要在哪些場景下使用?有啥坑?

  1. 加密
  2. 音視頻解碼
  3. 圖像操做
  4. 安全相關,好比hookt
  5. 增量更新
  6. 遊戲開發

NDK開發須要注意什麼?

[https://developer.android.com/training/articles/perf-jni.html]

使用JNI的流程?

  1. JAVA中聲明native 方法如private native String printJNI(String inputStr);
  2. 使用javah工具生成.h頭文件這時候頭文件中就會自動生成對應的函數JNIEXPORT jstring JNICALL Java_com_wenming_HelloWorld_printJNI
  3. 實現JNI原生函數源文件,新建HelloWorld.c文件,對剛纔自動生成的函數進行具體的邏輯書寫,例如返回一個java叫作HelloWorld的字符串等
  4. 編譯生成動態連接so文件**
  5. Java中調用Sysytem.load方法把剛纔的so庫加載進來,就能夠調用native方法了

如何經過JNI傳遞String對象

Java的String和C++的string是不能對等起來的,因此當咱們拿到.h文件下面的jstring對象,會作一次轉換咱們把jstring轉換爲C下面的char*類型, 獲取值 

constchar* str; 
str = env->GetStringUTFChars(prompt,false); 

賦予值 

char* tmpstr ="return string succeeded"; 
jstring rtstr = env->NewStringUTF(tmpstr); 


網絡優化

移動端獲取數據優化的幾個點

  1. 鏈接複用 : 
    節省鏈接創建時間,如開啓 keep-alive。 
    對於 Android 來講默認狀況下 HttpURLConnection 和 HttpClient 都開啓了 keep-alive。只是 2.2 以前 HttpURLConnection 存在影響鏈接池的 Bug,具體可見:Android HttpURLConnection 及 HttpClient 選擇
  2. 請求合併: 
    即將多個請求合併爲一個進行請求,比較常見的就是網頁中的 CSS Image Sprites。若是某個頁面內請求過多,也能夠考慮作必定的請求合併。
  3. 減小請求數據的大小: 
    對於post請求,body能夠作gzip壓縮的,header也能夠做數據壓縮(不過只支持http 2.0)。
  4. 返回的數據的body也能夠做gzip壓縮,body數據體積能夠縮小到原來的30%左右。(也能夠考慮壓縮返回的json數據的key數據的體積,尤爲是針對返回數據格式變化不大的狀況,支付寶聊天返回的數據用到了)
  5. 根據用戶的當前的網絡質量來判斷下載什麼質量的圖片(電商用的比較多)。

如何設計一個良好的網絡層?

[http://blog.csdn.net/column/details/simple-net.html]

如何防止重複發送網絡請求

點擊activity上的一個按鈕,發送網絡請求,在網絡比較慢的狀況下,用戶可能會繼續去點擊按鈕,這個時候,發送其餘無謂的請求,不知道你們是怎麼處理這類問題來攔截? 
HTTP header中加入max-age,這樣某個固定的時間內都將返回empty body,固然這個方法是死的,把時間徹底限制了,這個方法回掉也會一樣要執行屢次。 
還有個暈招,就是直接設置按鈕的clickable爲false,或者使用progressbar,相似於樓主的方法,好比點讚的場景。 
使用Map的話,在回掉的時候,仍是須要回收HashMap的,維護Map還不如只維護一個boolean呢。 
Volley中若是開了緩存的話, 相同的請求同時只會有一個去真正的請求, 後續都走緩存, 雖然不會請求屢次, 可是回調是會執行屢次的, 和這個需求不match

如何實現wap聯網

參考:[http://blog.csdn.net/asce1885/article/details/7844159]


測試與調試

如何調試Android應用程序

Debug 
Log

Android中經常使用的測試工具?

內存分析:mat,ddms,leakcanary 
靜態分析:find bugs 
壓力測試:monkey 
自動化測試:UIAutomatorMonkeyRunner,Rubotium


內存泄漏/內存溢出相關

內存泄漏問題

  1. 資源對象沒有關閉形成,如查詢數據庫沒有關閉遊標
  2. 構造Adapter時,沒有使用緩存ConvertView
  3. Bitmap對象在不使用時調用recycle()釋放內存
  4. context逃逸問題
  5. 註冊沒有取消,如動態註冊廣播在Activity銷燬前沒有unregisterReceiver
  6. 集合對象未清理,如無用時沒有釋放對象的引用
  7. 在Activity中使用非靜態的內部類,並開啓一個長時間運行的線程,由於內部類持有Activity的引用,會致使Activity原本能夠被gc時卻長期得不到回收

哪些狀況下發生OOM

  • 類的靜態變量持有大數據對象 靜態變量長期維持到大數據對象的引用,阻止垃圾回收。

  • 非靜態內部類存在靜態實例 非靜態內部類會維持一個到外部類實例的引用,若是非靜態內部類的實例是靜態的,就會間接長期維持着外部類的引用,阻止被回收掉。

  • 資源對象未關閉 資源性對象好比(Cursor,File文件等)每每都用了一些緩衝,咱們在不使用的時候,應該及時關閉它們, 以便它們的緩衝及時回收內存。它們的緩衝不只存在於java虛擬機內,還存在於java虛擬機外。 若是咱們僅僅是把它的引用設置爲null,而不關閉它們,每每會形成內存泄露。 解決辦法: 好比SQLiteCursor(在析構函數finalize(),若是咱們沒有關閉它,它本身會調close()關閉), 若是咱們沒有關閉它,系統在回收它時也會關閉它,可是這樣的效率過低了。 所以對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,而後才置爲null. 在咱們的程序退出時必定要確保咱們的資源性對象已經關閉。 程序中常常會進行查詢數據庫的操做,可是常常會有使用完畢Cursor後沒有關閉的狀況。若是咱們的查詢結果集比較小, 對內存的消耗不容易被發現,只有在常時間大量操做的狀況下才會復現內存問題,這樣就會給之後的測試和問題排查帶來困難和風險,記得try catch後,在finally方法中關閉鏈接

  • Handler內存泄漏 Handler做爲內部類存在於Activity中,可是Handler生命週期與Activity生命週期每每並非相同的,好比當Handler對象有Message在排隊,則沒法釋放,進而致使本該釋放的Acitivity也沒有辦法進行回收。 解決辦法

    • 聲明handler爲static類,這樣內部類就再也不持有外部類的引用了,就不會阻塞Activity的釋放
    • 若是內部類實在須要用到外部類的對象,可在其內部聲明一個弱引用引用外部類

一些不良代碼習慣 有些代碼並不形成內存泄露,可是他們的資源沒有獲得重用,頻繁的申請內存和銷燬內存,消耗CPU資源的同時,也引發內存抖動 解決方案 若是須要頻繁的申請內存對象和和釋放對象,能夠考慮使用對象池來增長對象的複用。 例如ListView即是採用這種思想,經過複用converview來避免頻繁的GC

如何排查OOM

參見:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html

如何避免OOM

1. 使用更加輕量的數據結構 例如,咱們能夠考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構。一般的HashMap的實現方式更加消耗內存,由於它須要一個額外的實例對象來記錄Mapping操做。另外,SparseArray更加高效,在於他們避免了對key與value的自動裝箱(autoboxing),而且避免了裝箱後的解箱。

2. 避免在Android裏面使用Enum Android官方培訓課程提到過「Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.」,具體原理請參考《Android性能優化典範(三)》,因此請避免在Android裏面使用到枚舉。

3. 減少Bitmap對象的內存佔用 Bitmap是一個極容易消耗內存的大胖子,減少建立出來的Bitmap的內存佔用可謂是重中之重,,一般來講有如下2個措施: inSampleSize:縮放比例,在把圖片載入內存以前,咱們須要先計算出一個合適的縮放比例,避免沒必要要的大圖載入。 decode format:解碼格式,選擇ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差別

4.Bitmap對象的複用 縮小Bitmap的同時,也須要提升BitMap對象的複用率,避免頻繁建立BitMap對象,複用的方法有如下2個措施 LRUCache : 「最近最少使用算法」在Android中有極其廣泛的應用。ListView與GridView等顯示大量圖片的控件裏,就是使用LRU的機制來緩存處理好的Bitmap,把近期最少使用的數據從緩存中移除,保留使用最頻繁的數據, inBitMap高級特性:利用inBitmap的高級特性提升Android系統在Bitmap分配與釋放執行效率。使用inBitmap屬性能夠告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的Bitmap會嘗試去使用以前那張Bitmap在Heap中所佔據的pixel data內存區域,而不是去問內存從新申請一塊區域來存放Bitmap。利用這種特性,即便是上千張的圖片,也只會僅僅只須要佔用屏幕所可以顯示的圖片數量的內存大小

4. 使用更小的圖片 在涉及給到資源圖片時,咱們須要特別留意這張圖片是否存在能夠壓縮的空間,是否可使用更小的圖片。儘可能使用更小的圖片不只能夠減小內存的使用,還能避免出現大量的InflationException。假設有一張很大的圖片被XML文件直接引用,頗有可能在初始化視圖時會由於內存不足而發生InflationException,這個問題的根本緣由實際上是發生了OOM。

5.StringBuilder 在有些時候,代碼中會須要使用到大量的字符串拼接的操做,這種時候有必要考慮使用StringBuilder來替代頻繁的「+」。

4.避免在onDraw方法裏面執行對象的建立 相似onDraw等頻繁調用的方法,必定須要注意避免在這裏作建立對象的操做,由於他會迅速增長內存的使用,並且很容易引發頻繁的gc,甚至是內存抖動。

5. 避免對象的內存泄露 android中內存泄漏的場景以及解決辦法,參考上一問


ANR錯誤

什麼是ANR

ANR全稱Application Not Responding,意思就是程序未響應。若是一個應用沒法響應用戶的輸入,系統就會彈出一個ANR對話框,用戶能夠自行選擇繼續等待亦或者是中止當前程序。一旦出現下面兩種狀況,則彈出ANR對話框 
1. 應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸) 
2. BroadcastReceiver未在10秒內完成相關的處理

Service在特定的時間內沒法處理完成 
超時的緣由通常有兩種: 
(1)當前的事件沒有機會獲得處理(UI線程正在處理前一個事件沒有及時完成或者looper被某種緣由阻塞住) 
(2)當前的事件正在處理,但沒有及時完成 
UI線程儘可能只作跟UI相關的工做,耗時的工做(數據庫操做,I/O,鏈接網絡或者其餘可能阻礙UI線程的操做)放入單獨的線程處理,儘可能用Handler來處理UI thread和thread之間的交互。 
UI線程主要包括以下: 
• Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick() 
• AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel() 
• Mainthread handler: handleMessage(), post(runnable r)

如何定位ANR錯誤

開發機器上,查看/data/anr/traces.text.最新的ANR信息在最開始部分.

如何避免ANR

避免ANR最核心的一點就是在主線程減小耗時操做.一般須要從如下幾個方案下手:

  • 使用子線程處理耗時IO操做。

  • 下降子線程優先級使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,不然仍然會下降程序響應,由於默認Thread的優先級和主線程相同。

  • 使用Handler處理子線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。

  • Activity的onCreate和onResume回調中儘可能避免耗時的代碼

  • BroadcastReceiver中onReceive代碼也要儘可能減小耗時操做建議使用IntentService處理。IntentService是一個異步的,會自動中止的服務,很好解決了傳統的Service中處理完耗時操做忘記中止並銷燬Service的問題


安全相關

本地存儲的數據怎麼加密好?好比:shared_prefs,sqlite數據,用戶名,密碼等.若是是aes加密,怎麼保存key?

密碼不要存在本地,通常保存token。最基本的要代碼混淆,能夠的話加殼,防止反編譯


系統相關

Android各版本API區別

參考:[http://blog.csdn.net/lijun952048910/article/details/7980562]

什麼是Dalvik虛擬機

Dalvik虛擬機是Android平臺的核心。它能夠支持.dex格式的程序的運行,.dex格式是專爲Dalvik設計的一種壓縮格式,能夠減小總體文件尺寸,提升I/O操做的速度,適合內存和處理器速度有限的系統

Dalvik虛擬機和JVM有什麼區別

  • Dalvik 基於寄存器,而 JVM 基於棧。基於寄存器的虛擬機對於更大的程序來講,在它們編譯的時候,花費的時間更短。
  • Dalvik執行.dex格式的字節碼,而JVM執行.class格式的字節碼

Android爲每一個應用程序分配的內存大小是多少

通常是16m或者24m,可是能夠經過android:largeHeap申請更多內存,具體參考: 
[https://liuzhichao.com/2016/use-android_largeHeap.html] 
[http://www.cnblogs.com/mythou/p/3203536.html]

如何解決方法數65k問題?

使用Android Studio 的gradle 能夠構建MutilDex

Android系統啓動流程分析

  1. 打開adb shell 而後執行ps命令,能夠看到首先執行的是init方法!找到init.c這個文件.
  2. 而後走init裏面的main方法,在這main方法裏面執行mkdir進行建立不少的文件夾,和掛載一些目錄
  3. 而後回去初始化init.rc這個配置文件!在這個配置文件裏面回去啓動孵化器這個服務,這個服務會去啓動app_process這個文件夾,這個文件夾裏面有個app_main.cpp這個文件!
  4. 而後在app_main.cpp這個c文件裏面在main方法裏面它會去啓動安卓的虛擬機,而後安卓虛擬機會去啓動os.zygoteinit這個服務!
  5. zygoteinit這是個java代碼寫的,而後咱們找到了main方法,在這個方法裏面咱們看到他首先設置虛擬機的最小堆內存爲5兆,而後走到preloadclasses()這個方法來加載安卓系統全部的2000多個類經過類加載器加載進來,好比activity,contentx,http,…(其實沒有必要一會兒所有加載下來,咱們能夠等用到的時候在加載也能夠!)
  6. 而後又走preloadresources()這個方法來預加載安卓中定義好的資源好比顏色,圖片,系統的id等等。。。都加載了!(其實這也是不必的! )
  7. 而後又走startSystemServer(),這個方法來加載系統的服務!他會先使用natvieJNI去調用C去初始化界面和聲音的服務,這就是咱們爲何先聽到聲音和界面的緣由!
  8. 最後等服務加載完成後也就啓動起來了!

總結 linux啓動->init進程啓動(加載init.rc配置)->zygote啓動->systemServer啓動,systemServer會經過init1和init2啓動navite世界和java世界_

相關文章
相關標籤/搜索