介紹自己負責的部分,如何實現的。
自定義view viewGroup
activity的啟動流程
事件傳遞及滑動沖突的處理
插件化(activity如何加載及資源處理
內存優化 ,如何避免oom
內存泄漏如何處理及如何排查
handler問題
圖片加載用的什么以及原理
從一堆數據里怎么查找最大的n個數
快速排序
字符串匹配
介紹自己負責的部分,如何實現的
這個把自己負責的模塊說清楚就好,一般有一下幾個方面可以說一下,前提是不要給自己挖坑
自己負責模塊在整個項目中的角色,也就是功能描述
開發前的自己的一些思考,比如對業務的抽象,接口的定義,協議的定義等等
開發編碼過程中遇到的難點以及坑
排查問題以及結解決方式
兼容性保證
性能優化
上線之后模塊導致crash的比例
自定義view viewGroup
這個就是約定的幾個方法,onMeasure,onLayout,onDraw,measure,layout,draw
同時注意寫方法的調用時機以及區別,比如onMeasure是個模版方法是在measure下調用的,這個方法在viewGroup里面,
自定義的這些就已經足夠了,如果還擴展一些更新問題,子線程能不能更新,是可以的,在ViewRootImpl沒創建之前可以更新,不同sdk這個類可能名字不一樣。
activity的啟動流程
這個肯定不是說activity的生命周期,是啟動加載過程,大致說下流程,具體的要自己看代碼了,大致過程有:
這里可能分好幾種情況,其實都差不很多,這里就說一種情況,startActivity這個怎么啟動Activity的,
startActivity->ActivityManagerService->ActivityThread->Activity,大概參與就這幾個核心類,里面經過了兩層binder通信,最后路由到IApplicationThread,然后到ActivityThread中的H消息隊列中啟動Activity,細節很多,可以在評論詢問。
事件傳遞及滑動沖突的處理
事件傳遞理解成責任鏈式調用就好,也就是從最內層到外層時間委派,如果事件consume了,那么就給這個view處理,不然從外向內冒泡,
沖突處理舉個實例就好,比如SlideMenu與banner或者ListView與Scrollview的沖突等等,說出基本思路就行,這些解決一般都是重寫那幾個事件方法,然后各種判斷就好
插件化(activity如何加載及資源處理)
Activity使用占坑hook加載,也可以使用靜態代理,靜態代理就需要自定義classloader,記住這個加載模式就行,再多細節在評論回復吧
,資源處理就是assetmanager的創建,然后資源沖突處理,簡單的可以構建多個assetmanager就沒有沖突問題,應為隔離了,如果使用一個那么
打包aapt定制一下就行,還有很多細節,在評論回復吧,說不完了。
內存優化 ,如何避免oom
內存優化太多要說的了,有套路的回答,基本就是避免跟gc配合好工作,比如:盡量復用對象,處理無用對象,避免內存泄漏,壓縮對象等等
,盡量將大對象特殊處理,比如bitmap占用內存較多,可以jni層與java層配合一起,大小壓縮,質量壓縮,imsimplesize的大小定義,規范等等,程序中有內存管理模塊,避免內存壓力大的時候
,能夠釋放內存,避免oom發生的幾率,還有很多方面,在評論回復吧。
內存泄漏如何處理及如何排查
內存泄漏最大的問題就是無用對象常駐內存,導致內存壓力很大,最后可能導致oom發生。盡量將對象生命周期可以在控制的能力之內,具體的在回復說吧,也很多場景,比如:context 除了特殊情況用activity,其他我們沒理由不用application。排查導出堆空間,然后mat分析,程序里面
用leackcanary定位。
handler問題
這個需要回復兩個基本的,首先handler的創建需要loop,loop怎么創建的,同時這個里面怎么保證loop線程安全的,還有就是消息如何分發的,也就是消息發送到接受的流程,
還有callback對消息處理的影響,這些足夠了,還可以說可以跨進程,這樣就更棒了,具體的在回復說,太多了。
圖片加載用的什么以及原理
圖片加載的太多了,說個自己非常熟悉的就行,不要給自己挖坑,都懂的,比如你熟悉uil,那就說具體的加載過程,
套路都差不多,都是創建圖片task,先從緩存取出來,取不到就去網絡下載,下載完之后,同時緩存起來,這里需要說下,線程池,隊列,pause,resume的具體細節,比如跟view,activity的綁定關系。回復具體說,也很多
從一堆數據里怎么查找最大的n個數
這個用歸并排序,或者直接快排,沒啥還說的。不會的自己google看算法,算法后面我會寫出來到文章里面。
快速排序
基本思想挖坑,分而治之,按照這個思路看代碼就行
字符串匹配
這個kmp算法,或者最基本的吧,不考慮時間,空間復雜度的條件下,但是不要說這個,太low了點。其實這些算法背下來就好,不是業務場景的,意義不大,但是必須要會,不然吃虧了
架構
其實架構沒有固定模式,能夠說出自己對架構的理解就很好,比如mvp,不同人對這個理解不一樣,最好的,夠用的,最適合業務的才是好架構,這個也很多要說,評論說吧。
熱點
如何保證Service不被殺死?
Android 進程不死從3個層面入手:
A.提供進程優先級,降低進程被殺死的概率方法一:監控手機鎖屏解鎖事件,在屏幕鎖屏時啟動1個像素的 Activity,在用戶解鎖時將 Activity 銷毀掉。方法二:啟動前臺service。方法三:提升service優先級:在AndroidManifest.xml文件中對于intent-filter可以通過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用于廣播。
B. 在進程被殺死后,進行拉活方法一:注冊高頻率廣播接收器,喚起進程。如網絡變化,解鎖屏幕,開機等方法二:雙進程相互喚起。方法三:依靠系統喚起。方法四:onDestroy方法里重啟service:service +broadcast? 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,重新啟動service;
C. 依靠第三方根據終端不同,在小米手機(包括 MIUI)接入小米推送、華為手機接入華為推送;其他手機可以考慮接入騰訊信鴿或極光推送與小米推送做 A/B Test。??
參考博客:Android 進程保活招式大全
ButterKnife原理ButterKnife對性能的影響很小,因為沒有使用使用反射,而是使用的Annotation Processing Tool(APT),注解處理器,javac中用于編譯時掃描和解析Java注解的工具。在編譯階段執行的,它的原理就是讀入Java源代碼,解析注解,然后生成新的Java代碼。新生成的Java代碼最后被編譯成Java字節碼,注解解析器不能改變讀入的Java 類,比如不能加入或刪除Java方法。
參考資料:最新ButterKnife框架原理Java Annotation 及幾個常用開源項目注解原理簡析ButterKnife 簡單原理實現
基礎
Activity和Fragment生命周期有哪些??
屏幕快照 2016-09-19 下午8.10.27.png
橫豎屏切換時候Activity的生命周期
不設置Activity的android:configChanges時,切屏會重新回掉各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次設置Activity的android:configChanges=”orientation”時,切屏還是會調用各個生命周期,切換橫豎屏只會執行一次設置Activity的android:configChanges=”orientation |keyboardHidden”時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法
AsyncTask源碼解析AsyncTask的缺陷和問題關于線程池:asynctask對應的線程池ThreadPoolExecutor都是進程范圍內共享的,都是static的,所以是asynctask控制著進程范圍內所有的子類實例。由于這個限制的存在,當使用默認線程池時,如果線程數超過線程池的最大容量,線程池就會爆掉(3.0后默認串行執行,不會出現這個問題)。針對這種情況,可以嘗試自定義線程池,配合asynctask使用。
關于默認線程池:核心線程池中最多有CPU_COUNT+1個,最多有CPU_COUNT*2+1個,線程等待隊列的最大等待數為128,但是可以自定義線程池。線程池是由AsyncTask來管理的,線程池允許tasks并行運行,需要注意的是并發情況下數據的一致性問題,新數據可能會被老數據覆蓋掉,類似volatile變量。所以希望tasks能夠串行運行的話,使用SERIAL_EXECUTOR。
AsyncTask在不同的SDK版本中的區別:調用AsyncTask的excute方法不能立即執行程序的原因分析及改善方案通過查閱官方文檔發現,AsyncTask首次引入時,異步任務是在一個獨立的線程中順序的執行,也就是說一次只能執行一個任務,不能并行的執行,從1.6開始,AsyncTask引入了線程池,支持同時執行5個異步任務,也就是說同時只能有5個線程運行,超過的線程只能等待,等待前面的線程某個執行完了才被調度和運行。換句話說,如果一個進程中的AsyncTask實例個數超過5個,那么假如前5個都運行很長時間的話,那么第6個只能等待機會了。這是AsyncTask的一個限制,而且對于2.3以前的版本無法解決。如果你的應用需要大量的后臺線程去執行任務,那么你只能放棄使用AsyncTask,自己創建線程池來管理Thread。不得不說,雖然AsyncTask較Thread使用起來方便,但是它最多只能同時運行5個線程,這也大大局限了它的實力,你必須要小心設計你的應用,錯開使用AsyncTask的時間,盡力做到分時,或者保證數量不會大于5個,否則就會遇到上次提到的問題。可能是Google意識到了AsyncTask的局限性了,從Android3.0開始對AsyncTask的API作出了一些調整:每次只啟動一個線程執行一個任務,完成之后再執行第二個任務,也就是相當于只有一個后臺線程在執行所提交的任務。
1.生命周期很多開發者會認為一個在Activity中創建的AsyncTask會隨著Activity的銷毀而銷毀。然而事實并非如此。AsyncTask會一直執行,直到doInBackground()方法執行完畢。然后,如果cancel(boolean)被調用,那么onCancelled(Result result)方法會被執行;否則,執行onPostExecute(Result result)方法。如果我們的Activity銷毀之前,沒有取消AsyncTask,這有可能讓我們的AsyncTask崩潰(crash)。因為它想要處理的view已經不在了。所以,我們總是必須確保在銷毀活動之前取消任務。總之,我們使用AsyncTask需要確保AsyncTask正確的取消。
2.內存泄漏如果AsyncTask被聲明為Activity的非靜態的內部類,那么AsyncTask會保留一個對Activity的引用。如果Activity已經被銷毀,AsyncTask的后臺線程還在執行,它將繼續在內存里保留這個引用,導致Activity無法被回收,引起內存泄漏。
3.結果丟失屏幕旋轉或Activity在后臺被系統殺掉等情況會導致Activity的重新創建,之前運行的AsyncTask會持有一個之前Activity的引用,這個引用已經無效,這時調用onPostExecute()再去更新界面將不再生效。
4.并行還是串行在Android1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了 修改,可以支持并行和串行,當想要串行執行時,直接執行execute()方法,如果需要執行executeOnExecutor(Executor)。
Acitivty的任務棧
使用android:launchMode="standard|singleInstance|single Task|singleTop"來控制Acivity任務棧。
任務棧是一種后進先出的結構。位于棧頂的Activity處于焦點狀態,當按下back按鈕的時候,棧內的Activity會一個一個的出棧,并且調用其onDestory()方法。如果棧內沒有Activity,那么系統就會回收這個棧,每個APP默認只有一個棧,以APP的包名來命名.
standard : 標準模式,每次啟動Activity都會創建一個新的Activity實例,并且將其壓入任務棧棧頂,而不管這個Activity是否已經存在。Activity的啟動三回調(onCreate()->onStart()->onResume())都會執行。
singleTop : 棧頂復用模式.這種模式下,如果新Activity已經位于任務棧的棧頂,那么此Activity不會被重新創建,所以它的啟動三回調就不會執行,同時Activity的onNewIntent()方法會被回調.如果Activity已經存在但是不在棧頂,那么作用于standard模式一樣.
singleTask: 棧內復用模式.創建這樣的Activity的時候,系統會先確認它所需任務棧已經創建,否則先創建任務棧.然后放入Activity,如果棧中已經有一個Activity實例,那么這個Activity就會被調到棧頂,onNewIntent(),并且singleTask會清理在當前Activity上面的所有Activity.(clear top)
singleInstance : 加強版的singleTask模式,這種模式的Activity只能單獨位于一個任務棧內,由于棧內復用的特性,后續請求均不會創建新的Activity,除非這個獨特的任務棧被系統銷毀了Activity的堆棧管理以ActivityRecord為單位,所有的ActivityRecord都放在一個List里面.可以認為一個ActivityRecord就是一個Activity棧
onSaveInstanceState() 與onRestoreIntanceState()用戶或者程序員主動去銷毀一個Activity的時候不會掉用,其他情況都會調動,來保存界面信息。如代碼中finish()或用戶按下back,不會掉用。
android中進程的優先級??
前臺進程:即與用戶正在交互的Activity或者Activity用到的Service等,如果系統內存不足時前臺進程是最后被殺死的
可見進程:可以是處于暫停狀態(onPause)的Activity或者綁定在其上的Service,即被用戶可見,但由于失去了焦點而不能與用戶交互
服務進程:其中運行著使用startService方法啟動的Service,雖然不被用戶可見,但是卻是用戶關心的,例如用戶正在非音樂界面聽的音樂或者正在非下載頁面自己下載的文件等;當系統要空間運行前兩者進程時才會被終止
后臺進程:其中運行著執行onStop方法而停止的程序,但是卻不是用戶當前關心的,例如后臺掛著的QQ,這樣的進程系統一旦沒了有內存就首先被殺死
空進程:不包含任何應用程序的程序組件的進程,這樣的進程系統是一般不會讓他存在的
Serializable和Parcelable序列化,表示將一個對象轉換成可存儲或可傳輸的狀態。序列化后的對象可以在網絡上進行傳輸,也可以存儲到本地。
Serializable(Java自帶):Serializable是序列化的意思,表示將一個對象轉換成可存儲或可傳輸的狀態。序列化后的對象可以在網絡上進行傳輸,也可以存儲到本地。
Parcelable(android 專用):除了Serializable之外,使用Parcelable也可以實現相同的效果,不過不同于將對象進行序列化,Parcelable方式的實現原理是將一個完整的對象進行分解,而分解后的每一部分都是Intent所支持的數據類型,這樣也就實現傳遞對象的功能了。
動畫
tween 補間動畫。通過指定View的初末狀態和變化時間、方式,對View的內容完成一系列的圖形變換來實現動畫效果。 Alpha, Scale ,Translate, Rotate。
frame 幀動畫 AnimationDrawable 控制 animation-list xml布局
PropertyAnimation 屬性動畫 3.0引入,屬性動畫核心思想是對值的變化。?
?屬性動畫詳解Property Animation 動畫有兩個步聚:1.計算屬性值2.為目標對象的屬性設置屬性值,即應用和刷新動畫
valuecaculate.png
計算屬性分為3個過程:?
過程一:計算已完成動畫分數 elapsed fraction 為了執行一個動畫,你需要創建一個 ValueAnimator,并且指定目標對象屬性的開始、結束值和持續時間。在調用 start 后的整個動畫過程中, ValueAnimator 會根據已經完成的動畫時間計算得到一個 0 到 1 之間的分數,代表該動畫的已完成動畫百分比。0 表示 0%,1 表示 100%。?
過程二:計算插值(動畫變化率)interpolated fraction 當 ValueAnimator 計算完已完成動畫分數后,它會調用當前設置的 TimeInterpolator,去計算得到一個 interpolated(插值)分數,在計算過程中,已完成動畫百分比會被加入到新的插值計算中。?
過程三:計算屬性值 當插值分數計算完成后,ValueAnimator 會根據插值分數調用合適的 TypeEvaluator 去計算運動中的屬性值。以上分析引入了兩個概念:已完成動畫分數(elapsed fraction)、插值分數( interpolated fraction )。
Android的數據存儲形式
SQLite:SQLite是一個輕量級的數據庫,支持基本的SQL語法,是常被采用的一種數據存儲方式。 Android為此數據庫提供了一個名為SQLiteDatabase的類,封裝了一些操作數據庫的api
SharedPreference: 以鍵值對的形勢儲存。其本質就是一個xml文件,常用于存儲較簡單的參數設置。
File: 即常說的文件(I/O)存儲方法,常用語存儲大數量的數據,但是缺點是更新數據將是一件困難的事情。
ContentProvider: Android系統中能實現所有應用程序共享的一種數據存儲方式,由于數據通常在各應用間的是互相私密的,所以此存儲方式較少使用,但是其又是必不可少的一種存儲方式。例如音頻,視頻,圖片和通訊錄,一般都可以采用此種方式進行存儲。每個Content Provider都會對外提供一個公共的URI(包裝成Uri對象),如果應用程序有數據需要共享時,就需要使用Content Provider為這些數據定義一個URI,然后其他的應用程序就通過Content Provider傳入這個URI來對數據進行操作。
Context相關
Activity和Service以及Application的Context是不一樣的,Activity繼承自ContextThemeWraper.其他的繼承自ContextWrapper.每一個Activity和Service以及Application的Context都是一個新的ContextImpl對象getApplication()用來獲取Application實例的,但是這個方法只有在Activity和Service中才能調用的到。那么也許在絕大多數情況下我們都是在Activity或者Service中使用Application的,但是如果在一些其它的場景,比如BroadcastReceiver中也想獲得Application的實例,這時就可以借助getApplicationContext()方法,getApplicationContext()比getApplication()方法的作用域會更廣一些,任何一個Context的實例,只要調用getApplicationContext()方法都可以拿到我們的Application對象。創建Toast和對話框不可以用Application 的context,只能用Activity的context。Context的數量等于Activity的個數 + Service的個數 + 1,這個1為Application
Android各版本新特性Android5.0新特性
MaterialDesign設計風格
支持多種設備
支持64位ART虛擬機
Android6.0新特性
大量漂亮流暢的動畫
支持快速充電的切換
支持文件夾拖拽應用
相機新增專業模式?
Android7.0新特性
分屏多任務
增強的Java8語言模式
夜間模式
Json
JSON的全程是JavaScript Object Notation,也就是JavaScript 對象表示法
JSON是存儲和交換文本信息的語法,類似XML,但是比XML更小、更快,更易解析
JSON是輕量級的文本數據交換格式,獨立于語言,具有自我描述性,更易理解
對象可以包含多個名稱/值對,比如:?
{"name":"zhangsan" , "age":25}
使用谷歌的GSON包進行解析在 Android Studio 里引入依賴:
compile 'com.google.code.gson:gson:2.7'
值得注意的是實體類中變量名稱必須和json中的值名相同。json1的解析我們這里的實體類是Student.class
Gson gson = new Gson();
Student student = gson.fromJson(json1, Student.class);
json2的解析我們可以解析成int數組,也可以解析成Integer的List。解析成數組:?
Gson gson = new Gson();
int[] ages = gson.fromJson(json2, int[].class);
解析成List:
Gson gson = new Gson();
List<Integer> ages = gson.fromJson(json2, new TypeToken<List<Integer>>(){}.getType);
json3的解析同樣可以解析成List或者數組,我們就直接解析成List.
Gson gson = new Gson();
List<Student> students = gson.fromJson(json3, new TypeToke<List<Student>>(){}.getType);
android中有哪幾種解析xml的類,官方推薦哪種?以及它們的原理和區別?
DOM解析???? 優點:1.XML樹在內存中完整存儲,因此可以直接修改其數據和結構.2.可以通過該解析器隨時訪問XML樹中的任何一個節點.3.DOM解析器的API在使用上也相對比較簡單.缺點:如果XML文檔體積比較大時,將文檔讀入內存是非常消耗系統資源的.使用場景:DOM 是用與平臺和語言無關的方式表示 XML 文檔的官方 W3C 標準.DOM 是以層次結構組織的節點的集合.這個層次結構允許開發人員在樹中尋找特定信息.分析該結構通常需要加載整個文檔和構造層次結構,然后才能進行任何工作.DOM是基于對象層次結構的.
SAX解析? 優點:SAX 對內存的要求比較低,因為它讓開發人員自己來決定所要處理的標簽.特別是當開發人員只需要處理文檔中所包含的部分數據時,SAX 這種擴展能力得到了更好的體現.缺點:用SAX方式進行XML解析時,需要順序執行,所以很難訪問到同一文檔中的不同數據.此外,在基于該方式的解析編碼過程也相對復雜.使用場景:對于含有數據量十分巨大,而又不用對文檔的所有數據進行遍歷或者分析的時候,使用該方法十分有效.該方法不用將整個文檔讀入內存,而只需讀取到程序所需的文檔標簽處即可.
Xmlpull解析? android SDK提供了xmlpull api,xmlpull和sax類似,是基于流(stream)操作文件,然后根據節點事件回調開發者編寫的處理程序.因為是基于流的處理,因此xmlpull和sax都比較節約內存資源,不會象dom那樣要把所有節點以對橡樹的形式展現在內存中.xmlpull比sax更簡明,而且不需要掃描完整個流.
Jar和Aar的區別
Jar包里面只有代碼,aar里面不光有代碼還包括代碼還包括資源文件,比如 drawable 文件,xml 資源文件。對于一些不常變動的 Android Library,我們可以直接引用 aar,加快編譯速度
什么是三級緩存(研究中)
三級緩存原理(研究中)
Android為每個應用程序分配的內存大小是多少android程序內存一般限制在16M,也有的是24M?
更新UI方式Activity.runOnUiThread(Runnable)View.post(Runnable),View.postDelay(Runnable,long)HandlerAsyncTask?
進階
引起內存泄漏的情況?
對于使用了BraodcastReceiver,ContentObserver,File,游標 Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者注銷。
靜態內部類持有外部成員變量(或context):可以使用弱引用或使用ApplicationContext。?
內部類持有外部類引用,異步任務中,持有外部成員變量。
集合中沒用的對象沒有及時remove。
不用的對象及時釋放,如使用完Bitmap后掉用recycle(),再賦null。?
handler引起的內存泄漏,MessageQueue里的消息如果在activity銷毀時沒有處理完,就會引起內存的泄漏,可以使用弱引用解決。
設置過的監聽不用時,及時移除。如在Destroy時及時remove。尤其以addListener開頭的,在Destroy中都需要remove。
activity泄漏可以使用LeakCanary。
Android 內存溢出解決方案(OOM) 整理總結?
在內存引用上做些處理,常用的有軟引用、弱引用??
在內存中加載圖片時直接在內存中作處理,如:邊界壓縮?
動態回收內存?
優化Dalvik虛擬機的堆內存分配?
自定義堆內存大小
Activity/Window/View三者的差別,fragment的特點
Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。?
在Activity中調用attach,創建了一個Window創建的window是其子類PhoneWindow,在attach中創建PhoneWindow在Activity中調用setContentView(R.layout.xxx)其中實際上是調用的getWindow().setContentView()調用PhoneWindow中的setContentView方法創建ParentView:? 作為ViewGroup的子類,實際是創建的DecorView(作為FramLayout的子類)將指定的R.layout.xxx進行填充通過布局填充器進行填充【其中的parent指的就是DecorView】調用到ViewGroup調用ViewGroup的removeAllView(),先將所有的view移除掉添加新的view:addView()?
Fragment 特點Fragment可以作為Activity界面的一部分組成出現;可以在一個Activity中同時出現多個Fragment,并且一個Fragment也可以在多個Activity中使用;在Activity運行過程中,可以添加、移除或者替換Fragment;Fragment可以響應自己的輸入事件,并且有自己的生命周期,它們的生命周期會受宿主Activity的生命周期影響。
JVM 和Dalvik虛擬機的區別?
JVM:.java -> javac -> .class -> jar -> .jar架構: 堆和棧的架構.?
DVM:.java -> javac -> .class -> dx.bat -> .dex架構: 寄存器(cpu上的一塊高速緩存)
怎么考慮數據傳輸的安全性如果應用對傳輸的數據沒有任何安全措施,攻擊者設置的釣魚網絡中更改DNS服務器。這臺服務器可以獲取用戶信息,或充當中間人與原服務器交換數據。在SSL/TLS通信中,客戶端通過數字證書判斷服務器是否可信,并采用證書的公鑰與服務器進行加密通信。
自定義View的相關方法 1.自定義屬性2.onLayout(Viewgroup)3.onMesure4.onDraw5.交互:onIntercepterTouchEvent()onTouchEvent()
事件傳遞機制 詳解當手指觸摸到屏幕時,系統就會調用相應View的onTouchEvent,并傳入一系列的action。?
dispatchTouchEvent的執行順序為:?
首先觸發ACTIVITY的dispatchTouchEvent,然后觸發ACTIVITY的onInterceptTouchEvent.然后觸發LAYOUT的dispatchTouchEvent,然后觸發LAYOUT的onInterceptTouchEvent這就解釋了重寫ViewGroup時必須調用super.dispatchTouchEvent();?
(1)dispatchTouchEvent:
此方法一般用于初步處理事件,因為動作是由此分發,所以通常會調用super.dispatchTouchEvent。這樣就會繼續調用onInterceptTouchEvent,再由onInterceptTouchEvent決定事件流向。
(2)onInterceptTouchEvent:
若返回值為true事件會傳遞到自己的onTouchEvent();若返回值為false傳遞到下一個View的dispatchTouchEvent();
(3)onTouchEvent():
若返回值為true,事件由自己消耗,后續動作讓其處理;若返回值為false,自己不消耗事件了,向上返回讓其他的父View的onTouchEvent接受處理
三大方法關系的偽代碼:如果當前View攔截事件,就交給自己的onTouchEvent去處理,否則就丟給子View繼續走相同的流程。
public boolean dispatchTouchEvent(MotionEvent ev)
{
??? boolean consume = false;
??? if(onInterceptTouchEvent(ev))
??? {
??????? consume = onTouchEvent(ev);
??? }
??? else
??? {
??????? consume = child.dispatchTouchEvent(ev);
??? }
??? return consume;
}
onTouchEvent的傳遞:
當有多個層級的View時,在父層級允許的情況下,這個action會一直傳遞直到遇到最深層的View。所以touch事件最先調用的是最底層View的onTouchEvent,如果View的onTouchEvent接收到某個touch action并做了相應處理,最后有兩種返回方式return true和return false;return true會告訴系統當前的View需要處理這次的touch事件,以后的系統發出的ACTION_MOVE,ACTION_UP還是需要繼續監聽并接收的,并且這次的action已經被處理掉了,父層的View是不可能觸發onTouchEvent的了。所以每一個action最多只能有一個onTouchEvent接口返回true。如果返回false,便會通知系統,當前View不關心這一次的touch事件,此時這個action會傳向父級,調用父級View的onTouchEvent。但是這一次的touch事件之后發出任何action,該View都不在接受,onTouchEvent在這一次的touch事件中再也不會觸發,也就是說一旦View返回false,那么之后的ACTION_MOVE,ACTION_UP等ACTION就不會在傳入這個View,但是下一次touch事件的action還是會傳進來的。
父層的onInterceptTouchEvent
前面說了底層的View能夠接收到這次的事件有一個前提條件:在父層允許的情況下。假設不改變父層級的dispatch方法,在系統調用底層onTouchEvent之前會調用父View的onInterceptTouchEvent方法判斷,父層View是否要截獲本次touch事件之后的action。如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不會向深層的View傳遞,統統都會傳給父層View的onTouchEvent,就是說父層已經截獲了這次touch事件,之后的action也不必詢問onInterceptTouchEvent,在這次的touch事件之后發出的action時onInterceptTouchEvent不會再被調用,直到下一次touch事件的來臨。如果onInterceptTouchEvent返回false,那么本次action將發送給更深層的View,并且之后的每一次action都會詢問父層的onInterceptTouchEvent需不需要截獲本次touch事件。只有ViewGroup才有onInterceptTouchEvent方法,因為一個普通的View肯定是位于最深層的View,touch能夠傳到這里已經是最后一站了,肯定會調用View的onTouchEvent()。
底層View的getParent().requestDisallowInterceptTouchEvent(true)
對于底層的View來說,有一種方法可以阻止父層的View獲取touch事件,就是調用getParent().requestDisallowInterceptTouchEvent(true)方法。一旦底層View收到touch的action后調用這個方法那么父層View就不會再調用onInterceptTouchEvent了,也無法截獲以后的action(如果父層ViewGroup和最底層View需要截獲不同焦點,或不同手勢的touch,不能使用這個寫死)。
ART和Dalvik區別
art上應用啟動快,運行快,但是耗費更多存儲空間,安裝時間長,總的來說ART的功效就是”空間換時間”。
ART: Ahead of TimeDalvik: Just in Time
什么是Dalvik:Dalvik是Google公司自己設計用于Android平臺的Java虛擬機。Dalvik虛擬機是Google等廠商合作開發的Android移動設備平臺的核心組成部分之一,它可以支持已轉換為.dex(即Dalvik Executable)格式的Java應用程序的運行,.dex格式是專為Dalvik應用設計的一種壓縮格式,適合內存和處理器速度有限的系統。Dalvik經過優化,允許在有限的內存中同時運行多個虛擬機的實例,并且每一個Dalvik應用作為獨立的Linux進程執行。獨立的進程可以防止在虛擬機崩潰的時候所有程序都被關閉。
什么是ART:Android操作系統已經成熟,Google的Android團隊開始將注意力轉向一些底層組件,其中之一是負責應用程序運行的Dalvik運行時。Google開發者已經花了兩年時間開發更快執行效率更高更省電的替代ART運行時。ART代表Android Runtime,其處理應用程序執行的方式完全不同于Dalvik,Dalvik是依靠一個Just-In-Time(JIT)編譯器去解釋字節碼。開發者編譯后的應用代碼需要通過一個解釋器在用戶的設備上運行,這一機制并不高效,但讓應用能更容易在不同硬件和架構上運行。ART則完全改變了這套做法,在應用安裝的時候就預編譯字節碼到機器語言,這一機制叫Ahead-Of-Time(AOT)編譯。在移除解釋代碼這一過程后,應用程序執行將更有效率,啟動更快。
ART優點:
系統性能的顯著提升應用啟動更快、運行更快、體驗更流暢、觸感反饋更及時。更長的電池續航能力支持更低的硬件?
ART缺點:更大的存儲空間占用,可能會增加10%-20%更長的應用安裝時間
Scroller原理
Scroller執行流程里面的三個核心方法
mScroller.startScroll()mScroller.computeScrollOffset()view.computeScroll()1、在mScroller.startScroll()中為滑動做了一些初始化準備,比如:起始坐標,滑動的距離和方向以及持續時間(有默認值),動畫開始時間等。
2、mScroller.computeScrollOffset()方法主要是根據當前已經消逝的時間來計算當前的坐標點。因為在mScroller.startScroll()中設置了動畫時間,那么在computeScrollOffset()方法中依據已經消逝的時間就很容易得到當前時刻應該所處的位置并將其保存在變量mCurrX和mCurrY中。除此之外該方法還可判斷動畫是否已經結束。
Android中Java和JavaScript交互
webView.addJavaScriptInterface(new Object(){xxx}, "xxx");
1
答案:可以使用WebView控件執行JavaScript腳本,并且可以在JavaScript中執行Java代碼。要想讓WebView控件執行JavaScript,需要調用WebSettings.setJavaScriptEnabled方法,代碼如下:
WebView webView = (WebView)findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
//設置WebView支持JavaScript
webSettings.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
JavaScript調用Java方法需要使用WebView.addJavascriptInterface方法設置JavaScript調用的Java方法,代碼如下:
webView.addJavascriptInterface(new Object()
{
??? //JavaScript調用的方法
??? public String process(String value)
??? {
??????? //處理代碼
??????? return result;
??? }
}, "demo");?????? //demo是Java對象映射到JavaScript中的對象名
可以使用下面的JavaScript代碼調用process方法,代碼如下:
<script language="javascript">
??? function search()
??? {
??????? //調用searchWord方法
??????? result.innerHTML = "<font color='red'>" + window.demo.process('data') + "</font>";
??? }
SurfaceView和View的最本質的區別
SurfaceView是在一個新起的單獨線程中可以重新繪制畫面,而view必須在UI的主線程中更新畫面。
在UI的主線程中更新畫面可能會引發問題,比如你更新的時間過長,那么你的主UI線程就會被你正在畫的函數阻塞。那么將無法響應按鍵、觸屏等消息。當使用SurfaceView由于是在新的線程中更新畫面所以不會阻塞你的UI主線程。但這也帶來了另外一個問題,就是事件同步。比如你觸屏了一下,你需要SurfaceView中thread處理,一般就需要有一個event queue的設計來保存touchevent,這會稍稍復雜一點,因為涉及到線程安全。常用的設計模式單例,適配器,策略模式等常用的設計模式需要掌握?
單例
public class Singleton{?
private volatile static Singleton mSingleton;
private Singleton(){
}
public static Singleton getInstance(){
? if(mSingleton == null){\\A
??? synchronized(Singleton.class){\\C
???? if(mSingleton == null)
????? mSingleton = new Singleton();\\B
????? }
??? }
??? return mSingleton;
? }
}
ANR排錯
1、ANR排錯一般有三種情況
KeyDispatchTimeout(5 seconds) –主要類型按鍵或觸摸事件在特定時間內無響應
BroadcastTimeout(10 secends) –BroadcastReceiver在特定時間內無法處理完成??
ServiceTimeout(20 secends) –小概率事件 Service在特定的時間內無法處理完成發生原因主線程被IO操作(從4.0之后網絡IO不允許在主線程中)阻塞。主線程中存在耗時的計算主線程中錯誤的操作,比如Thread.wait或者Thread.sleep等 Android系統會監控程序的響應狀況使用AsyncTask處理耗時IO操作。
2、如何避免
UI線程盡量只做跟UI相關的工作耗時的操作(比如數據庫操作,I/O,連接網絡或者別的有可能阻塞UI線程的操作)把它放在單獨的線程處理盡量用Handler來處理UIthread和別的thread之間的交互.使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,否則仍然會降低程序響應,因為默認Thread的優先級和主線程相同。使用Handler處理工作線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。Activity的onCreate和onResume回調中盡量避免耗時的代碼BroadcastReceiver中onReceive代碼也要盡量減少耗時,建議使用IntentService處理。
3、ANR定位和修正如果開發機器上出現問題,我們可以通過查看/data/anr/traces.txt即可,最新的ANR信息在最開始部分。?
Android程序運行時權限與文件系統權限1,Linux 文件系統權限。不同的用戶對文件有不同的讀寫執行權限。在android系統中,system和應用程序是分開的,system里的數據是不可更改的。2,Android中有3種權限,進程權限UserID,簽名,應用申明權限。每次安裝時,系統根據包名為應用分配唯一的userID,不同的userID運行在不同的進程里,進程間的內存是獨立的,不可以相互訪問,除非通過特定的Binder機制。Android提供了如下的一種機制,可以使兩個apk打破前面講的這種壁壘。在AndroidManifest.xml中利用sharedUserId屬性給不同的package分配相同的userID,通過這樣做,兩個package可以被當做同一個程序,系統會分配給兩個程序相同的UserID。當然,基于安全考慮,兩個package需要有相同的簽名,否則沒有驗證也就沒有意義了。
如何讓程序自動啟動定義一個Braodcastreceiver,action為BOOT——COMPLETE,接受到廣播后啟動程序。
View繪制流程
斷電續傳詳解?
Handler機制andriod提供了Handler 和 Looper 來滿足線程間的通信。Handler先進先出原則。Looper類用來管理特定線程內對象之間的消息交換(MessageExchange)。Looper: 一個線程可以產生一個Looper對象,由它來管理此線程里的MessageQueue(消息隊列)。Handler: 你可以構造Handler對象來與Looper溝通,以便push新消息到MessageQueue里;或者接收Looper從Message Queue取出)所送來的消息。Message Queue(消息隊列):用來存放線程放入的消息。線程:UIthread 通常就是main thread,而Android啟動程序時會替它建立一個MessageQueue。
ListView卡頓原因Adapter的getView方法里面convertView沒有使用setTag和getTag方式;在getView方法里面ViewHolder初始化后的賦值或者是多個控件的顯示狀態和背景的顯示沒有優化好,抑或是里面含有復雜的計算和耗時操作;在getView方法里面 inflate的row 嵌套太深(布局過于復雜)或者是布局里面有大圖片或者背景所致;Adapter多余或者不合理的notifySetDataChanged;listview 被多層嵌套,多次的onMessure導致卡頓,如果多層嵌套無法避免,建議把listview的高和寬設置為fill_parent. 如果是代碼繼承的listview,那么也請你別忘記為你的繼承類添加上LayoutPrams,注意高和寬都是fill_parent的;
啟動一個程序,可以主界面點擊圖標進入,也可以從一個程序中跳轉過去,二者有什么區別?是因為啟動程序(主界面也是一個app),發現了在這個程序中存在一個設置為?
<category android:name="android.intent.category.LAUNCHER" />
的activity,所以這個launcher會把icon提出來,放在主界面上。當用戶點擊icon的時候,發出一個Intent:
Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);
跳過去可以跳到任意允許的頁面,如一個程序可以下載,那么真正下載的頁面可能不是首頁(也有可能是首頁),這時還是構造一個Intent,startActivity.這個intent中的action可能有多種view,download都有可能。系統會根據第三方程序向系統注冊的功能,為你的Intent選擇可以打開的程序或者頁面。所以唯一的一點不同的是從icon的點擊啟動的intent的action是相對單一的,從程序中跳轉或者啟動可能樣式更多一些。本質是相同的。
AIDL的全稱是什么?如何工作?能處理哪些類型的數據?AIDL全稱Android Interface Definition Language(Android接口描述語言)是一種接口描述語言; 編譯器可以通過aidl文件生成一段代碼,通過預先定義的接口達到兩個進程內部通信進程跨界訪問對象的目的.AIDL的IPC的機制和COM或CORBA類似, 是基于接口的,但它是輕量級的。它使用代理類在客戶端和實現層間傳遞值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相關類.; 2. 調用aidl產生的class.理論上, 參數可以傳遞基本數據類型和String, 還有就是Bundle的派生類, 不過在Eclipse中,目前的ADT不支持Bundle做為參數,具體實現步驟如下:1、創建AIDL文件, 在這個文件里面定義接口, 該接口定義了可供客戶端訪問的方法和屬性。2、編譯AIDL文件, 用Ant的話, 可能需要手動, 使用Eclipse plugin的話,可以根據adil文件自動生產java文件并編譯, 不需要人為介入.3、在Java文件中, 實現AIDL中定義的接口. 編譯器會根據AIDL接口, 產生一個JAVA接口。這個接口有一個名為Stub的內部抽象類,它繼承擴展了接口并實現了遠程調用需要的幾個方法。接下來就需要自己去實現自定義的幾個接口了.4、向客戶端提供接口ITaskBinder, 如果寫的是service,擴展該Service并重載onBind ()方法來返回一個實現上述接口的類的實例。5、在服務器端回調客戶端的函數. 前提是當客戶端獲取的IBinder接口的時候,要去注冊回調函數, 只有這樣, 服務器端才知道該調用那些函數AIDL語法很簡單,可以用來聲明一個帶一個或多個方法的接口,也可以傳遞參數和返回值。 由于遠程調用的需要, 這些參數和返回值并不是任何類型.下面是些AIDL支持的數據類型:
不需要import聲明的簡單Java編程語言類型(int,boolean等)
String, CharSequence不需要特殊聲明
List, Map和Parcelables類型, 這些類型內所包含的數據成員也只能是簡單數據類型, String等其他比支持的類型.(另外: 我沒嘗試Parcelables, 在Eclipse+ADT下編譯不過, 或許以后會有所支持).實現接口時有幾個原則:1.拋出的異常不要返回給調用者. 跨進程拋異常處理是不可取的.2.IPC調用是同步的。如果你知道一個IPC服務需要超過幾毫秒的時間才能完成地話,你應該避免在Activity的主線程中調用。也就是IPC調用會掛起應用程序導致界面失去響應. 這種情況應該考慮單起一個線程來處理.3.不能在AIDL接口中聲明靜態屬性。IPC的調用步驟:?
聲明一個接口類型的變量,該接口類型在.aidl文件中定義。?
實現ServiceConnection。?
調用ApplicationContext.bindService(),并在ServiceConnection實現中進行傳遞.?
在ServiceConnection.onServiceConnected()實現中,你會接收一個IBinder實例(被調用的Service). 調用YourInterfaceName.Stub.asInterface((IBinder)service)將參數轉換為YourInterface類型。?
調用接口中定義的方法。你總要檢測到DeadObjectException異常,該異常在連接斷開時被拋出。它只會被遠程方法拋出。???
斷開連接,調用接口實例中的ApplicationContext.unbindService()參考:http://buaadallas.blog.51cto.com/399160/372090
aidl主要就是幫助我們完成了包裝數據和解包的過程,并調用了transact過程,而用來傳遞的數據包我們就稱為parcel
AIDL: xxx.aidl->xxx.java,注冊service
用aidl定義需要被調用方法接口實現這些方法調用這些方法?
FC(Force Close)
什么時候會出現???
Error
OOM,內存溢出
StackOverFlowError
Runtime,比如說空指針異常?
解決的辦法
注意內存的使用和管理
使用Thread.UncaughtExceptionHandler接口
性能優化
界面優化太多重疊的背景(overdraw)
這個問題其實最容易解決,建議就是檢查你在布局和代碼中設置的背景,有些背景是隱藏在底下的,它永遠不可能顯示出來,這種沒必要的背景一定要移除,因為它很可能會嚴重影響到app的性能。如果采用的是selector的背景,將normal狀態的color設置為”@android:color/transparent”,也同樣可以解決問題。
太多重疊的View
第一個建議是 :使用ViewStub來加載一些不常用的布局,它是一個輕量級且默認是不可見的視圖,可以動態的加載一個布局,只要你用到這個重疊著的View的時候才加載,推遲加載的時間。
第二個建議是:如果使用了類似Viewpager+Fragment這樣的組合或者有多個Fragment在一個界面上,需要控制Fragment的顯示和隱藏,盡量使用動態的Inflation view,它的性能要比SetVisibility好。
復雜的Layout層級
這里的建議比較多一些,首先推薦使用Android提供的布局工具Hierarchy Viewer來檢查和優化布局。第一個建議是:如果嵌套的線性布局加深了布局層次,可以使用相對布局來取代。第二個建議是:用標簽來合并布局。第三個建議是:用標簽來重用布局,抽取通用的布局可以讓布局的邏輯更清晰明了。記住,這些建議的最終目的都是使得你的Layout在Hierarchy Viewer里變得寬而淺,而不是窄而深。
總結:可以考慮多使用merge和include,ViewStub。盡量使布局淺平,根布局盡量少使用RelactivityLayout,因為RelactivityLayout每次需要測量2次。
內存優化核心思想:減少內存使用,能不new的不new,能少分配的少分配。因為分配更多的內存就意味著發生更多的GC,每次觸發GC都會占用CPU時間,影響性能。
集合優化:Android提供了一系列優化過后的數據集合工具類,如SparseArray、SparseBooleanArray、LongSparseArray,使用這些API可以讓我們的程序更加高效。HashMap工具類會相對比較低效,因為它需要為每一個鍵值對都提供一個對象入口,而SparseArray就避免掉了基本數據類型轉換成對象數據類型的時間。?
Bitmap優化:讀取一個Bitmap圖片的時候,千萬不要去加載不需要的分辨率。可以壓縮圖片等操作。???
盡量避免使用依賴注入框架。
避免創作不必要的對象:字符串拼接使用StringBuffer,StringBuilder。
onDraw方法里面不要執行對象的創建.
重寫onTrimMemory,根據傳入的參數,進行內存釋放。
使用static final 優化成員變量。?
移動端獲取網絡數據優化的幾個點
連接復用:節省連接建立時間,如開啟 keep-alive。對于Android來說默認情況下HttpURLConnection和HttpClient都開啟了keep-alive。只是2.2之前HttpURLConnection存在影響連接池的Bug,具體可見:Android HttpURLConnection及HttpClient選擇
請求合并:即將多個請求合并為一個進行請求,比較常見的就是網頁中的CSS Image Sprites。如果某個頁面內請求過多,也可以考慮做一定的請求合并。
減少請求數據的大小:對于post請求,body可以做gzip壓縮的,header也可以做數據壓縮(不過只支持http 2.0)。返回數據的body也可以做gzip壓縮,body數據體積可以縮小到原來的30%左右。(也可以考慮壓縮返回的json數據的key數據的體積,尤其是針對返回數據格式變化不大的情況,支付寶聊天返回的數據用到了)根據用戶的當前的網絡質量來判斷下載什么質量的圖片(電商用的比較多)
高級
Android系統啟動過程,App啟動過程]從桌面點擊到activity啟動的過程
1.Launcher線程捕獲onclick的點擊事件,調用Launcher.startActivitySafely,進一步調用Launcher.startActivity,最后調用父類Activity的startActivity。
2.Activity和ActivityManagerService交互,引入Instrumentation,將啟動請求交給Instrumentation,調用Instrumentation.execStartActivity。
3.調用ActivityManagerService的startActivity方法,這里做了進程切換(具體過程請查看源碼)。
4.開啟Activity,調用onCreate方法
熱布丁原因:因為一個dvm中存儲方法id用的是short類型,導致dex中方法不能超過65536個原理:將編譯好的class文件拆分打包成兩個dex,繞過dex方法數量的限制以及安裝時的檢查,在運行時再動態加載第二個dex文件中。使用Dexclassloader。
動態加載(也叫插件化技術)動態加載主要解決3個技術問題:1,使用ClassLoader加載類。2,資源訪問。3,生命周期管理。?
參考1、Android熱補丁動態修復技術系列 2、Android 利用 APT 技術在編譯期生成代碼3、Android中的動態加載機制 4、掌閱 Android App 插件補丁實踐 (ZeusPlugin)5、插件化開發從入門到深入6、Android Hotfix 新方案——Amigo 源碼解讀(from diycode) 【更新于2016年9月2號】7、插件化由理論到實踐【更新于2016年9月3日】8Android插件化原理解析9 Android動態加載技術三個關鍵問題詳解10 Android apk動態加載機制的研究
Binder機制
跨進程間通信(IPC):四大組件之間通過Intent互相跳轉,Android實現IPC的方式是binder機制。
android中的跨進程通信的實現(一)——遠程調用過程和aidlAndroid中的Binder機制的簡要理解Android中的Binder機制的簡要理解二
Android系統的架構?
屏幕快照 2016-09-07 上午9.26.57.png
android的系統架構和其操作系統一樣,采用了分層的架構。從架構圖看,android分為四個層,從高層到低層分別是應用程序層、應用程序框架層、系統運行庫層和linux核心層。 1.應用程序 Android會同一系列核心應用程序包一起發布,該應用程序包包括email客戶端,SMS短消息程序,日歷,地圖,瀏覽器,聯系人管理程序等。所有的應用程序都是使用JAVA語言編寫的。 2.應用程序框架 開發人員也可以完全訪問核心應用程序所使用的API框架。該應用程序的架構設計簡化了組件的重用;任何一個應用程序都可以發布它的功能塊并且任何其它的應用程序都可以使用其所發布的功能塊(不過得遵循框架的安全性限制)。同樣,該應用程序重用機制也使用戶可以方便的替換程序組件。 隱藏在每個應用后面的是一系列的服務和系統, 其中包括; 豐富而又可擴展的視圖(Views),可以用來構建應用程序, 它包括列表(lists),網格(grids),文本框(text boxes),按鈕(buttons), 甚至可嵌入的web瀏覽器。
內容提供器(Content Providers)使得應用程序可以訪問另一個應用程序的數據(如聯系人數據庫), 或者共享它們自己的數據 資源管理器(Resource Manager)提供 非代碼資源的訪問,如本地字符串,圖形,和布局文件( layout files )。
通知管理器 (Notification Manager) 使得應用程序可以在狀態欄中顯示自定義的提示信息。 * 活動管理器( Activity Manager) 用來管理應用程序生命周期并提供常用的導航回退功能。 有關更多的細節和怎樣從頭寫一個應用程序,請參考 如何編寫一個 Android 應用程序.?
3.系統運行庫 1)程序庫 Android 包含一些C/C++庫,這些庫能被Android系統中不同的組件使用。它們通過 Android 應用程序框架為開發者提供服務。以下是一些核心庫: 系統 C 庫 - 一個從 BSD 繼承來的標準 C 系統函數庫( libc ), 它是專門為基于 embedded linux 的設備定制的。 媒體庫 - 基于 PacketVideo OpenCORE;該庫支持多種常用的音頻、視頻格式回放和錄制,同時支持靜態圖像文件。編碼格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。 Surface Manager - 對顯示子系統的管理,并且為多個應用程序提 供了2D和3D圖層的無縫融合。 ? LibWebCore - 一個最新的web瀏覽器引擎用,支持Android瀏覽器和一個可嵌入的web視圖。 SGL- 底層的2D圖形引擎 3D libraries - 基于OpenGL ES 1.0 APIs實現;該庫可以使用硬件 3D加速(如果可用)或者使用高度優化的3D軟加速。 FreeType -位圖(bitmap)和矢量(vector)字體顯示。 SQLite - 一個對于所有應用程序可用,功能強勁的輕型關系型數據庫引擎。 2)Android 運行庫 Android 包括了一個核心庫,該核心庫提供了JAVA編程語言核心庫的大多數功能。 每一個Android應用程序都在它自己的進程中運行,都擁有一個獨立的Dalvik虛擬機實例。Dalvik被設計成一個設備可以同時高效地運行多個虛擬系統。 Dalvik虛擬機執行(.dex)的Dalvik可執行文件,該格式文件針對小內存使用做了優化。同時虛擬機是基于寄存器的,所有的類都經由JAVA編譯器編譯,然后通過SDK中 的 “dx” 工具轉化成.dex格式由虛擬機執行。 Dalvik虛擬機依賴于linux內核的一些功能,比如線程機制和底層內存管理機制。 *4.Linux 內核**Android 的核心系統服務依賴于 Linux 2.6 內核,如安全性,內存管理,進程管理, 網絡協議棧和驅動模型。 Linux 內核也同時作為硬件和軟件棧之間的抽象層。