1. 程式人生 > >Android面試題集

Android面試題集

頁面 nts 可見 集成 培訓課程 繼續 ide imp 進入

前幾天整理了Java面試題集合,今天再來整理下Android相關的面試題集合.假設你希望能得到最新的消息,能夠關註https://github.com/closedevice/interview-about,我會不斷的添加和修正相關問題的描寫敘述.

基礎

談談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。完畢引用的更新

Asynctask為什麽要設置為僅僅能夠一次任務

考慮到線程安全問題

若Activity已經銷毀,此時AsynTask運行完並返回結果,會報異常麽?

當一個App旋轉時,整個Activity會被銷毀和重建。當Activity重新啟動時,AsyncTask中對該Activity的引用是無效的,因此onPostExecute()就不會起作用,若AsynTask正在運行,折會報 view not attached to window manager 異常

同樣也是生命周期的問題。在 Activity 的onDestory()方法中調用Asyntask.cancal方法。讓二者的生命周期同步

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

Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並非生命周期方法,不同於 onCreate()、onPause()等生命周期方法,它們並不一定會被觸發。當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷毀一個Activity。onSaveInstanceState() 會被調用。

可是當用戶主動去銷毀一個Activity時,比如在應用中按返回鍵,onSaveInstanceState()就不會被調用。除非該activity是被用戶主動銷毀的,通常onSaveInstanceState()僅僅適合用於保存一些暫時性的狀態,而onPause()適合用於數據的持久化保存。

介紹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實例進入。

LaunchMode使用場景

  1. singleTop適合接收通知啟動的內容顯示頁面。


    比如,某個新聞client的新聞內容頁面,假設收到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配置像窗花圖紙。

Activity啟動Service的兩種方式

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

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

棧一般以包名命名,兩個應用的簽名和udid要同樣

Fragment是什麽?你以前遇到哪些有關Fragment的問題?

Fragment能夠作為Activity界面的一部分組成出現.一個Activity中能夠同一時候出現多個Fragment,並一個Fragment也能夠在多個Activity中使用.

在Activity中能夠加入,刪除,替換Fragment.Fragment能夠響應自己的輸入時間,而且有自己的生命周期,但其生命周期收Activity影響.

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();
     }

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操作數據僅僅需兩步: 1、調用Activity的ContentResolver獲取ContentResolver對象。 2、依據須要調用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應用中驗證碼登錄都有哪些實現方案

驗證碼應該僅僅有兩種獲取方式: 從server端獲取圖片, 通過短信服務,將驗證碼發送給client這兩種

為什麽要設計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是非靜態內部類的話。就非常easy出現內存泄露。假設是靜態的話,你就不能直接引用外部類,迫使你關註怎樣避免相互引用。 所以將 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的繪制的位置,比方,一個button在動畫過後。不在原來的位置。可是觸發點擊事件的仍然是原來的坐標。

  • 屬性動畫(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的屬性。什麽意思呢?比方說。如今屏幕的左上角有一個button,然後我們通過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個button,點擊事件是絕對不會觸發的。由於實際上這個button還是停留在屏幕的左上角,僅僅只是補間動畫將這個button繪制到了屏幕的右下角而已。


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上的一個button,發送網絡請求,在網絡比較慢的情況下。用戶可能會繼續去點擊button,這個時候,發送其它無謂的請求,不知道大家是怎麽處理這類問題來攔截?
HTTP header中加入max-age,這樣某個固定的時間內都將返回empty body,當然這種方法是死的,把時間全然限制了,這種方法回掉也會同樣要運行多次。
還有個暈招,就是直接設置button的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後沒有關閉的情況。

    假設我們的查詢結果集比較小, 對內存的消耗不easy被發現。僅僅有在常時間大量操作的情況下才會復現內存問題。這樣就會給以後的測試和問題排查帶來困難和風險。記得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是一個極easy消耗內存的大胖子,減小創建出來的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等頻繁調用的方法,一定須要註意避免在這裏做創建對象的操作,由於他會迅速添加內存的使用。而且非常easy引起頻繁的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數據,username,password等.假設是aes加密,怎麽保存key?

password不要存在本地,一般保存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世界_

Android面試題集