國內一線互聯網公司內部面試題庫

如下面試題來自於百度、小米、樂視、美團、5八、獵豹、360、新浪、搜狐內部題庫html

熟悉本文中列出的知識點會大大增長經過前兩輪技術面試的概率。java

歡迎一線公司員工提交內部面試題庫,歡迎star。 ##目錄android

java基礎git

接口的意義-百度
抽象類的意義-樂視
內部類的做用-樂視
父類的靜態方法可否被子類重寫-獵豹
java排序算法-美團
列舉java的集合和繼承關係-百度-美團
java虛擬機的特性-百度-樂視
哪些狀況下的對象會被垃圾回收機制處理掉-美團-小米
進程和線程的區別-獵豹-美團
==和equals和hashCode的區別-樂視
常見的排序算法時間複雜度-小米
HashMap的實現原理-美團
java狀態機
int-char-long各佔多少字節數
int與integer的區別
string-stringbuffer-stringbuilder區別-小米-樂視-百度
java多態-樂視
什麼致使線程阻塞-58-美團
抽象類接口區別-360
容器類之間的區別-樂視-美團
內部類
hashmap和hashtable的區別-樂視-小米
ArrayMap對比HashMap
安卓程序員

如何導入外部數據庫
本地廣播和全局廣播有什麼差異
intentService做用是什麼,AIDL解決了什麼問題?-小米
Activity,Window,View三者的差異,fragment的特色?-360
描述一次網絡請求的流程-新浪
Handler、Thread和HandlerThread的差異-小米
低版本SDK實現高版本api-小米
Ubuntu編譯安卓系統-百度
launch mode應用場景-百度-小米-樂視
Touch事件傳遞流程-小米
view繪製流程-百度
多線程-360
線程同步-百度
什麼狀況致使內存泄漏-美團
ANR定位和修正
什麼狀況致使oom-樂視-美團
Android Service與Activity之間通訊的幾種方式
Android各個版本API的區別
Android代碼中實現WAP方式聯網-360
如何保證service在後臺不被kill
Requestlayout,onlayout,onDraw,DrawChild區別與聯繫-獵豹
invalidate()和postInvalidate() 的區別及使用-百度
Android動畫框架實現原理
Android爲每一個應用程序分配的內存大小是多少?-美團
Android View刷新機制-百度-美團
LinearLayout對比RelativeLayout-百度
優化自定義view百度-樂視-小米
ContentProvider-樂視
fragment生命週期
volley解析-美團-樂視
Android Glide源碼解析
Android 設計模式
架構設計-搜狐
Android屬性動畫特性-樂視-小米
專題github

性能優化
架構分析
阿里巴巴
騰訊
###java面試

####接口的意義-百度算法

規範、擴展、回調數據庫

####抽象類的意義-樂視編程

爲其子類提供一個公共的類型 封裝子類中得重複內容 定義抽象方法,子類雖然有不一樣的實現 可是定義是一致的

####內部類的做用-樂視

內部類能夠用多個實例,每一個實例都有本身的狀態信息,而且與其餘外圍對象的信息相互獨立。
在單個外圍類中,可讓多個內部類以不一樣的方式實現同一個接口,或者繼承同一個類。
建立內部類對象的時刻並不依賴於外圍類對象的建立。
內部類並無使人迷惑的「is-a」關係,他就是一個獨立的實體。
內部類提供了更好的封裝,除了該外圍類,其餘類都不能訪問
####父類的靜態方法可否被子類重寫-獵豹

不能

子類繼承父類後,用相同的靜態方法和非靜態方法,這時非靜態方法覆蓋父類中的方法(即方法重寫),父類的該靜態方法被隱藏(若是對象是父類則調用該隱藏的方法),另外子類可繼承父類的靜態與非靜態方法,至於方法重載我以爲它其中一要素就是在同一類中,不能說父類中的什麼方法與子類裏的什麼方法是方法重載的體現

####java排序算法-美團

http://blog.csdn.net/qy1387/article/details/7752973

####列舉java的集合和繼承關係-百度-美團

 

####java虛擬機的特性-百度-樂視

Java語言的一個很是重要的特色就是與平臺的無關性。而使用Java虛擬機是實現這一特色的關鍵。通常的高級語言若是要在不一樣的平臺上運行,至少須要編譯成不一樣的目標代碼。而引入Java語言虛擬機後,Java語言在不一樣平臺上運行時不須要從新編譯。Java語言使用模式Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就能夠在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。

####哪些狀況下的對象會被垃圾回收機制處理掉-美團-小米

Java 垃圾回收機制最基本的作法是分代回收。內存中的區域被劃分紅不一樣的世代,對象根據其存活的時間被保存在對應世代的區域中。通常的實現是劃分紅3個世代:年輕、年老和永久。內存的分配是發生在年輕世代中的。當一個對象存活時間足夠長的時候,它就會被複制到年老世代中。對於不一樣的世代能夠使用不一樣的垃圾回收算法。進行世代劃分的出發點是對應用中對象存活時間進行研究以後得出的統計規律。通常來講,一個應用中的大部分對象的存活時間都很短。好比局部變量的存活時間就只在方法的執行過程當中。基於這一點,對於年輕世代的垃圾回收算法就能夠頗有針對性。

####進程和線程的區別-獵豹-美團

簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。

線程的劃分尺度小於進程,使得多線程程序的併發性高。

另外,進程在執行過程當中擁有獨立的內存單元,而多個線程共享內存,從而極大地提升了程序的運行效率。

線程在執行過程當中與進程仍是有區別的。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。可是線程不可以獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分能夠同時執行。但操做系統並無將多個線程看作多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程是具備必定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程本身基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),可是它可與同屬一個進程的其餘的線程共享進程所擁有的所有資源.

一個線程能夠建立和撤銷另外一個線程;同一個進程中的多個線程之間能夠併發執行.

進程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。若是有興趣深刻的話,我建議大家看看《現代操做系統》或者《操做系統的設計與實現》。對就個問題說得比較清楚。

####java中==和equals和hashCode的區別-樂視

http://blog.csdn.net/tiantiandjava/article/details/46988461

####常見的排序算法時間複雜度-小米

 

####HashMap的實現原理-美團

HashMap概述: HashMap是基於哈希表的Map接口的非同步實現。此實現提供全部可選的映射操做,並容許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恆久不變。
HashMap的數據結構: 在java編程語言中,最基本的結構就是兩種,一個是數組,另一個是模擬指針(引用),全部的數據結構均可以用這兩個基本結構來構造的,HashMap也不例外。HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。


從上圖中能夠看出,HashMap底層就是一個數組結構,數組中的每一項又是一個鏈表。當新建一個HashMap的時候,就會初始化一個數組。

####狀態機

http://www.jdon.com/designpatterns/designpattern_State.htm

####int-char-long各佔多少字節數

byte 位數 8 字節數 1

short 16 2

int 32 4

long 64 8

float 32 4

double 64 8

char 16 2

####int與integer的區別

http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226903.html

####string-stringbuffer-stringbuilder區別-小米-樂視-百度

String 字符串常量

StringBuffer 字符串變量(線程安全)

StringBuilder 字符串變量(非線程安全)

簡要的說, String 類型和 StringBuffer 類型的主要性能區別其實在於 String 是不可變的對象, 所以在每次對 String 類型進行改變的時候其實都等同於生成了一個新的 String 對象,而後將指針指向新的 String 對象,因此常常改變內容的字符串最好不要用String ,由於每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了之後,JVM 的 GC 就會開始工做,那速度是必定會至關慢的。

而若是是使用 StringBuffer 類則結果就不同了,每次結果都會對 StringBuffer 對象自己進行操做,而不是生成新的對象,再改變對象引用。因此在通常狀況下咱們推薦使用 StringBuffer ,特別是字符串對象常常改變的狀況下。而在某些特別狀況下, String 對象的字符串拼接實際上是被 JVM 解釋成了 StringBuffer 對象的拼接,因此這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是如下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的:

String S1 = "This is only a" + "simple" + " test";
StringBuffer Sb = new StringBuffer("This is only a").append("simple").append("test");
你會很驚訝的發現,生成 String S1 對象的速度簡直太快了,而這個時候 StringBuffer 竟然速度上根本一點都不佔優點。其實這是 JVM 的一個把戲,在 JVM 眼裏,這個 String S1 = 「This is only a」 + 「 simple」 + 「test」; 其實就是: String S1 = 「This is only a simple test」; 因此固然不須要太多的時間了。但你們這裏要注意的是,若是你的字符串是來自另外的 String 對象的話,速度就沒那麼快了,譬如: String S2 = 「This is only a」; String S3 = 「 simple」; String S4 = 「 test」; String S1 = S2 +S3 + S4; 這時候 JVM 會規規矩矩的按照原來的方式去作

在大部分狀況下 StringBuffer > String

StringBuffer

Java.lang.StringBuffer線程安全的可變字符序列。一個相似於 String 的字符串緩衝區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但經過某些方法調用能夠改變該序列的長度和內容。

可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致。

StringBuffer 上的主要操做是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每一個方法都能有效地將給定的數據轉換成字符串,而後將該字符串的字符追加或插入到字符串緩衝區中。append 方法始終將這些字符添加到緩衝區的末端;而 insert 方法則在指定的點添加字符。

例如,若是 z 引用一個當前內容是「start」的字符串緩衝區對象,則此方法調用 z.append("le") 會使字符串緩衝區包含「startle」,而 z.insert(4, "le") 將更改字符串緩衝區,使之包含「starlet」。

在大部分狀況下 StringBuilder > StringBuffer

java.lang.StringBuilder

java.lang.StringBuilder一個可變的字符序列是5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用做 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。若是可能,建議優先採用該類,由於在大多數實現中,它比 StringBuffer 要快。二者的方法基本相同

####java多態-樂視

Java多態性理解

Java中多態性的實現

什麼是多態

面向對象的三大特性:封裝、繼承、多態。從必定角度來看,封裝和繼承幾乎都是爲多態而準備的。這是咱們最後一個概念,也是最重要的知識點。

多態的定義:指容許不一樣類的對象對同一消息作出響應。即同一消息能夠根據發送對象的不一樣而採用多種不一樣的行爲方式。(發送消息就是函數調用)

實現多態的技術稱爲:動態綁定(dynamic binding),是指在執行期間判斷所引用對象的實 際類型,根據其實際的類型調用其相應的方法。

多態的做用:消除類型之間的耦合關係。

現實中,關於多態的例子不勝枚舉。比方說按下 F1 鍵這個動做,若是當前在 Flash 界面下彈出的就是 AS 3 的幫助文檔;若是當前在 Word 下彈出的就是 Word 幫助;在 Windows 下彈出的就是 Windows 幫助和支持。同一個事件發生在不一樣的對象上會產生不一樣的結果。 下面是多態存在的三個必要條件,要求你們作夢時都能背出來!

多態存在的三個必要條件 1、要有繼承; 2、要有重寫; 3、父類引用指向子類對象。

多態的好處:

1.可替換性(substitutability)。多態對已存在代碼具備可替換性。例如,多態對圓Circle類工做,對其餘任何圓形幾何體,如圓環,也一樣工做。

2.可擴充性(extensibility)。多態對代碼具備可擴充性。增長新的子類不影響已存在類的多態性、繼承性,以及其餘特性的運行和操做。實際上新加子類更容易得到多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。

3.接口性(interface-ability)。多態是超類經過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。如圖8.3 所示。圖中超類Shape規定了兩個實現多態的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere爲了實現多態,完善或者覆蓋這兩個接口方法。

4.靈活性(flexibility)。它在應用中體現了靈活多樣的操做,提升了使用效率。

5.簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤爲在處理大量對象的運算和操做時,這個特色尤其突出和重要。

Java中多態的實現方式:接口實現,繼承父類進行方法重寫,同一個類中進行方法重載。

####什麼致使線程阻塞-58-美團

線程的阻塞

爲了解決對共享存儲區的訪問衝突,Java 引入了同步機制,如今讓咱們來考察多個線程對共享資源的訪問,顯然同步機制已經不夠了,由於在任意時刻所要求的資源不必定已經準備好了被訪問,反過來,同一時刻準備好了的資源也可能不止一個。爲了解決這種狀況下的訪問控制問題,Java 引入了對阻塞機制的支持.

阻塞指的是暫停一個線程的執行以等待某個條件發生(如某資源就緒),學過操做系統的同窗對它必定已經很熟悉了。Java 提供了大量方法來支持阻塞,下面讓咱們逐一分析。

sleep() 方法:sleep() 容許 指定以毫秒爲單位的一段時間做爲參數,它使得線程在指定的時間內進入阻塞狀態,不能獲得CPU 時間,指定的時間一過,線程從新進入可執行狀態。 典型地,sleep() 被用在等待某個資源就緒的情形:測試發現條件不知足後,讓線程阻塞一段時間後從新測試,直到條件知足爲止。
suspend() 和 resume() 方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,而且不會自動恢復,必須其對應的resume() 被調用,才能使得線程從新進入可執行狀態。典型地,suspend() 和 resume() 被用在等待另外一個線程產生的結果的情形:測試發現結果尚未產生後,讓線程阻塞,另外一個線程產生告終果後,調用 resume() 使其恢復。
yield() 方法:yield() 使得線程放棄當前分得的 CPU 時間,可是不使線程阻塞,即線程仍處於可執行狀態,隨時可能再次分得 CPU 時間。調用 yield() 的效果等價於調度程序認爲該線程已執行了足夠的時間從而轉到另外一個線程.
wait() 和 notify() 方法:兩個方法配套使用,wait() 使得線程進入阻塞狀態,它有兩種形式,一種容許 指定以毫秒爲單位的一段時間做爲參數,另外一種沒有參數,前者當對應的 notify() 被調用或者超出指定時間時線程從新進入可執行狀態,後者則必須對應的 notify() 被調用.
初看起來它們與 suspend() 和 resume() 方法對沒有什麼分別,可是事實上它們是大相徑庭的。區別的核心在於,前面敘述的全部方法,阻塞時都不會釋放佔用的鎖(若是佔用了的話),而這一對方法則相反。

上述的核心區別致使了一系列的細節上的區別。

首先,前面敘述的全部方法都隸屬於 Thread 類,可是這一對卻直接隸屬於 Object 類,也就是說,全部對象都擁有這一對方法。初看起來這十分難以想象,可是實際上倒是很天然的,由於這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具備的,調用任意對象的 wait() 方法致使線程阻塞,而且該對象上的鎖被釋放。而調用 任意對象的notify()方法則致使因調用該對象的 wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到得到鎖後才真正可執行)。

其次,前面敘述的全部方法均可在任何位置調用,可是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在synchronized 方法或塊中當前線程才佔有鎖,纔有鎖能夠釋放。一樣的道理,調用這一對方法的對象上的鎖必須爲當前線程所擁有,這樣纔有鎖能夠釋放。所以,這一對方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的上鎖對象就是調用這一對方法的對象。若不知足這一條件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。

wait() 和 notify() 方法的上述特性決定了它們常常和synchronized 方法或塊一塊兒使用,將它們和操做系統的進程間通訊機制做一個比較就會發現它們的類似性:synchronized方法或塊提供了相似於操做系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則至關於 block 和wakeup 原語(這一對方法均聲明爲 synchronized)。它們的結合使得咱們能夠實現操做系統上一系列精妙的進程間通訊的算法(如信號量算法),並用於解決各類複雜的線程間通訊問題。

關於 wait() 和 notify() 方法最後再說明兩點:

第一:調用 notify() 方法致使解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,咱們沒法預料哪個線程將會被選擇,因此編程時要特別當心,避免因這種不肯定性而產生問題。

第二:除了 notify(),還有一個方法 notifyAll() 也可起到相似做用,惟一的區別在於,調用 notifyAll() 方法將把因調用該對象的 wait() 方法而阻塞的全部線程一次性所有解除阻塞。固然,只有得到鎖的那一個線程才能進入可執行狀態。

談到阻塞,就不能不談一談死鎖,略一分析就能發現,suspend() 方法和不指定超時期限的 wait() 方法的調用均可能產生死鎖。遺憾的是,Java 並不在語言級別上支持死鎖的避免,咱們在編程中必須當心地避免死鎖。

以上咱們對 Java 中實現線程阻塞的各類方法做了一番分析,咱們重點分析了 wait() 和 notify() 方法,由於它們的功能最強大,使用也最靈活,可是這也致使了它們的效率較低,較容易出錯。實際使用中咱們應該靈活使用各類方法,以便更好地達到咱們的目的。

####抽象類接口區別-360

默認的方法實現 抽象類能夠有默認的方法實現徹底是抽象的。接口根本不存在方法的實現

實現 子類使用extends關鍵字來繼承抽象類。若是子類不是抽象類的話,它須要提供抽象類中全部聲明的方法的實現。 子類使用關鍵字implements來實現接口。它須要提供接口中全部聲明的方法的實現

構造器 抽象類能夠有構造器 接口不能有構造器

與正常Java類的區別 除了你不能實例化抽象類以外,它和普通Java類沒有任何區 接口是徹底不一樣的類型

訪問修飾符 抽象方法能夠有public、protected和default這些修飾符 接口方法默認修飾符是public。你不能夠使用其它修飾符。

main方法 抽象方法能夠有main方法而且咱們能夠運行它 接口沒有main方法,所以咱們不能運行它。

多繼承 抽象類在java語言中所表示的是一種繼承關係,一個子類只能存在一個父類,可是能夠存在多個接口。

速度 它比接口速度要快 接口是稍微有點慢的,由於它須要時間去尋找在類中實現的方法。

添加新方法 若是你往抽象類中添加新的方法,你能夠給它提供默認的實現。所以你不須要改變你如今的代碼。 若是你往接口中添加方法,那麼你必須改變實現該接口的類。

####容器類之間的區別-樂視-美團

http://www.cnblogs.com/yuanermen/archive/2009/08/05/1539917.html http://alexyyek.github.io/2015/04/06/Collection/ http://tianmaying.com/tutorial/java_collection

####內部類

http://www.cnblogs.com/chenssy/p/3388487.html

####hashmap和hashtable的區別-樂視-小米

http://www.233.com/ncre2/JAVA/jichu/20100717/084230917.html

####ArrayMap對比HashMap

http://lvable.com/?p=217

###Android

####如何導入外部數據庫

把原數據庫包括在項目源碼的 res/raw

android系統下數據庫應該存放在 /data/data/com..(package name)/ 目錄下,因此咱們須要作的是把已有的數據庫傳入那個目錄下.操做方法是用FileInputStream讀取原數據庫,再用FileOutputStream把讀取到的東西寫入到那個目錄.

####本地廣播和全局廣播有什麼差異

因廣播數據在本應用範圍內傳播,不用擔憂隱私數據泄露的問題。 不用擔憂別的應用僞造廣播,形成安全隱患。 相比在系統內發送全局廣播,它更高效。

####intentService做用是什麼,AIDL解決了什麼問題-小米

生成一個默認的且與主線程互相獨立的工做者線程來執行全部傳送至onStartCommand() 方法的Intetnt。

生成一個工做隊列來傳送Intent對象給你的onHandleIntent()方法,同一時刻只傳送一個Intent對象,這樣一來,你就沒必要擔憂多線程的問題。在全部的請求(Intent)都被執行完之後會自動中止服務,因此,你不須要本身去調用stopSelf()方法來中止。

該服務提供了一個onBind()方法的默認實現,它返回null

提供了一個onStartCommand()方法的默認實現,它將Intent先傳送至工做隊列,而後從工做隊列中每次取出一個傳送至onHandleIntent()方法,在該方法中對Intent對相應的處理。

AIDL (Android Interface Definition Language) 是一種IDL 語言,用於生成能夠在Android設備上兩個進程之間進行進程間通訊(interprocess communication, IPC)的代碼。若是在一個進程中(例如Activity)要調用另外一個進程中(例如Service)對象的操做,就能夠使用AIDL生成可序列化的參數。 AIDL IPC機制是面向接口的,像COM或Corba同樣,可是更加輕量級。它是使用代理類在客戶端和實現端傳遞數據。

####Activity/Window/View三者的差異,fragment的特色-360

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的生命週期影響。
####描述一次網絡請求的流程-新浪

?

####Handler,Thread和HandlerThread的差異-小米

http://blog.csdn.net/guolin_blog/article/details/9991569

http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/

從Android中Thread(java.lang.Thread -> java.lang.Object)描述能夠看出,Android的Thread沒有對Java的Thread作任何封裝,可是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread作了不少便利Android系統的封裝。

android.os.Handler能夠經過Looper對象實例化,並運行於另外的線程中,Android提供了讓Handler運行於其它線程的線程實現,也是就HandlerThread。HandlerThread對象start後能夠得到其Looper對象,而且使用這個Looper對象實例Handler。

####低版本SDK實現高版本api-小米

本身實現或@TargetApi annotation

####Ubuntu編譯安卓系統-百度

進入源碼根目錄
. build/envsetup.sh
lunch
full(編譯所有)
userdebug(選擇編譯版本)
make -j8(開啓8個線程編譯)
####LaunchMode應用場景-百度-小米-樂視

standard,建立一個新的Activity。

singleTop,棧頂不是該類型的Activity,建立一個新的Activity。不然,onNewIntent。

singleTask,回退棧中沒有該類型的Activity,建立Activity,不然,onNewIntent+ClearTop。

注意:

設置了"singleTask"啓動模式的Activity,它在啓動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的Task存在; 若是存在這樣的Task,它就會在這個Task中啓動,不然就會在新的任務棧中啓動。所以, 若是咱們想要設置了"singleTask"啓動模式的Activity在新的任務中啓動,就要爲它設置一個獨立的taskAffinity屬性值。
若是設置了"singleTask"啓動模式的Activity不是在新的任務中啓動時,它會在已有的任務中查看是否已經存在相應的Activity實例, 若是存在,就會把位於這個Activity實例上面的Activity所有結束掉,即最終這個Activity 實例會位於任務的Stack頂端中。
在一個任務棧中只有一個」singleTask」啓動模式的Activity存在。他的上面能夠有其餘的Activity。這點與singleInstance是有區別的。
singleInstance,回退棧中,只有這一個Activity,沒有其餘Activity。

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

例如,某個新聞客戶端的新聞內容頁面,若是收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。

singleTask適合做爲程序入口點。

例如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent,而且會清空主界面上面的其餘頁面。

singleInstance應用場景:

鬧鈴的響鈴界面。 你之前設置了一個鬧鈴:上午6點。在上午5點58分,你啓動了鬧鈴設置界面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天;在6點時,鬧鈴響了,而且彈出了一個對話框形式的 Activity(名爲 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵,回到的是微信的聊天界面,這是由於 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 所以退出以後這個 Task 的棧空了。若是是以 SingleTask 打開 AlarmAlertActivity,那麼當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設置界面。

####Touch事件傳遞流程-小米

http://hanhailong.com/2015/09/24/Android-%E4%B8%89%E5%BC%A0%E5%9B%BE%E6%90%9E%E5%AE%9ATouch%E4%BA%8B%E4%BB%B6%E4%BC%A0%E9%80%92%E6%9C%BA%E5%88%B6/

####View繪製流程-百度

http://www.codekk.com/blogs/detail/54cfab086c4761e5001b253f

####多線程-360

Activity.runOnUiThread(Runnable)
View.post(Runnable),View.postDelay(Runnable,long)
Handler
AsyncTask
####線程同步-百度

http://www.itzhai.com/java-based-notebook-thread-synchronization-problem-solving-synchronization-problems-synchronized-block-synchronized-methods.html#read-more

http://www.juwends.com/tech/android/android-inter-thread-comm.html

單例

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;
}
}
####什麼狀況致使內存泄漏-美團

1.資源對象沒關閉形成的內存泄漏

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

2.構造Adapter時,沒有使用緩存的convertView

描述: 以構造ListView的BaseAdapter爲例,在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 來向ListView提供每個item所須要的view對象。初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化必定數量的 view對象,同時ListView會將這些view對象緩存起來。當向上滾動ListView時,原先位於最上面的list item的view對象會被回收,而後被用來構造新出現的最下面的list item。這個構造過程就是由getView()方法完成的,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。由此能夠看出,若是咱們不去使用 convertView,而是每次都在getView()中從新實例化一個View對象的話,即浪費資源也浪費時間,也會使得內存佔用愈來愈大。 ListView回收list item的view對象的過程能夠查看: android.widget.AbsListView.java --> voidaddScrapView(View scrap) 方法。 示例代碼:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = new Xxx(...);
... ...
return view;
}
修正示例代碼:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = null;
if (convertView != null) {
view = convertView;
populate(view, getItem(position));
...
} else {
view = new Xxx(...);
...
}
return view;
}
3.Bitmap對象不在使用時調用recycle()釋放內存

描述: 有時咱們會手工的操做Bitmap對象,若是一個Bitmap對象比較佔內存,當它不在被使用的時候,能夠調用Bitmap.recycle()方法回收此對象的像素所佔用的內存,但這不是必須的,視狀況而定。能夠看一下代碼中的註釋:

/** ?Free up the memory associated with thisbitmap's pixels, and mark the ?bitmap as "dead", meaning itwill throw an exception if getPixels() or ?setPixels() is called, and will drawnothing. This operation cannot be ?reversed, so it should only be called ifyou are sure there are no ?further uses for the bitmap. This is anadvanced call, and normally need ?not be called, since the normal GCprocess will free up this memory when ?there are no more references to thisbitmap. */

4.試着使用關於application的context來替代和activity相關的context

這是一個很隱晦的內存泄漏的狀況。有一種簡單的方法來避免context相關的內存泄漏。最顯著地一個是避免context逃出他本身的範圍以外。使用Application context。這個context的生存週期和你的應用的生存週期同樣長,而不是取決於activity的生存週期。若是你想保持一個長期生存的對象,而且這個對象須要一個context,記得使用application對象。你能夠經過調用 Context.getApplicationContext() or Activity.getApplication()來得到。更多的請看這篇文章如何避免 Android內存泄漏。

5.註冊沒取消形成的內存泄漏

一些Android程序可能引用咱們的Anroid程序的對象(好比註冊機制)。即便咱們的Android程序已經結束了,可是別的引用程序仍然還有對咱們的Android程序的某個對象的引用,泄漏的內存依然不能被垃圾回收。調用registerReceiver後未調用unregisterReceiver。 好比:假設咱們但願在鎖屏界面(LockScreen)中,監聽系統中的電話服務以獲取一些信息(如信號強度等),則能夠在LockScreen中定義一個 PhoneStateListener的對象,同時將它註冊到TelephonyManager服務中。對於LockScreen對象,當須要顯示鎖屏界面的時候就會建立一個LockScreen對象,而當鎖屏界面消失的時候LockScreen對象就會被釋放掉。 可是若是在釋放 LockScreen對象的時候忘記取消咱們以前註冊的PhoneStateListener對象,則會致使LockScreen沒法被垃圾回收。若是不斷的使鎖屏界面顯示和消失,則最終會因爲大量的LockScreen對象沒有辦法被回收而引發OutOfMemory,使得system_process 進程掛掉。 雖然有些系統程序,它自己好像是能夠自動取消註冊的(固然不及時),可是咱們仍是應該在咱們的程序中明確的取消註冊,程序結束時應該把全部的註冊都取消掉。

6.集合中對象沒清理形成的內存泄漏

咱們一般把一些對象的引用加入到了集合中,當咱們不須要該對象時,並無把它的引用從集合中清理掉,這樣這個集合就會愈來愈大。若是這個集合是static的話,那狀況就更嚴重了。

####ANR定位和修正

若是開發機器上出現問題,咱們能夠經過查看/data/anr/traces.txt便可,最新的ANR信息在最開始部分。

主線程被IO操做(從4.0以後網絡IO不容許在主線程中)阻塞。

主線程中存在耗時的計算

主線程中錯誤的操做,好比Thread.wait或者Thread.sleep等 Android系統會監控程序的響應情況,一旦出現下面兩種狀況,則彈出ANR對話框

應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸)

BroadcastReceiver未在10秒內完成相關的處理

Service在特定的時間內沒法處理完成 20秒

使用AsyncTask處理耗時IO操做。

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

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

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

BroadcastReceiver中onReceive代碼也要儘可能減小耗時,建議使用IntentService處理。

####什麼狀況致使oom-樂視-美團

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

1)使用更加輕量的數據結構 2)Android裏面使用Enum 3)Bitmap對象的內存佔用 4)更大的圖片 5)onDraw方法裏面執行對象的建立 6)StringBuilder

####Service與Activity之間通訊的幾種方式

經過Binder對象
經過broadcast(廣播)的形式
####Android各個版本API的區別

http://blog.csdn.net/lijun952048910/article/details/7980562

####Android代碼中實現WAP方式聯網-360

http://blog.csdn.net/asce1885/article/details/7844159

####如何保證service在後臺不被Kill

1、onStartCommand方法,返回START_STICKY

START_STICKY 在運行onStartCommand後service進程被kill後,那將保留在開始狀態,可是不保留那些傳入的intent。不久後service就會再次嘗試從新建立,由於保留在開始狀態,在建立 service後將保證調用onstartCommand。若是沒有傳遞任何開始命令給service,那將獲取到null的intent。

START_NOT_STICKY 在運行onStartCommand後service進程被kill後,而且沒有新的intent傳遞給它。Service將移出開始狀態,而且直到新的明顯的方法(startService)調用才從新建立。由於若是沒有傳遞任何未決定的intent那麼service是不會啓動,也就是期間onstartCommand不會接收到任何null的intent。

START_REDELIVER_INTENT 在運行onStartCommand後service進程被kill後,系統將會再次啓動service,並傳入最後一個intent給onstartCommand。直到調用stopSelf(int)才中止傳遞intent。若是在被kill後還有未處理好的intent,那被kill後服務仍是會自動啓動。所以onstartCommand不會接收到任何null的intent。

2、提高service優先級

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

3、提高service進程優先級

Android中的進程是託管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。Android將進程分爲6個等級,它們按優先級順序由高到低依次是:

前臺進程( FOREGROUND_APP)
可視進程(VISIBLE_APP )
次要服務進程(SECONDARY_SERVER )
後臺進程 (HIDDEN_APP)
內容供應節點(CONTENT_PROVIDER)
空進程(EMPTY_APP)
當service運行在低內存的環境時,將會kill掉一些存在的進程。所以進程的優先級將會很重要,能夠使用startForeground 將service放到前臺狀態。這樣在低內存時被kill的概率會低一些。

4、onDestroy方法裏重啓service

service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,從新啓動service;

5、Application加上Persistent屬性

6、監聽系統廣播判斷Service狀態

經過系統的一些廣播,好比:手機重啓、界面喚醒、應用狀態改變等等監聽並捕獲到,而後判斷咱們的Service是否還存活,別忘記加權限啊。

####Requestlayout,onlayout,onDraw,DrawChild區別與聯繫-獵豹

requestLayout()方法 :會致使調用measure()過程 和 layout()過程 。 將會根據標誌位判斷是否須要ondraw

onLayout()方法(若是該View是ViewGroup對象,須要實現該方法,對每一個子視圖進行佈局)

調用onDraw()方法繪製視圖自己 (每一個View都須要重載該方法,ViewGroup不須要實現該方法)

drawChild()去從新回調每一個子視圖的draw()方法

####invalidate()和postInvalidate()的區別及使用-百度

http://blog.csdn.net/mars2639/article/details/6650876

####Android動畫框架實現原理

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

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

android程序內存通常限制在16M,也有的是24M

####View刷新機制-百度-美團

由ViewRoot對象的performTraversals()方法調用draw()方法發起繪製該View樹,值得注意的是每次發起繪圖時,並不會從新繪製每一個View樹的視圖,而只會從新繪製那些「須要重繪」的視圖,View類內部變量包含了一個標誌位DRAWN,當該視圖須要重繪時,就會爲該View添加該標誌位。

調用流程 :

mView.draw()開始繪製,draw()方法實現的功能以下:

繪製該View的背景
爲顯示漸變框作一些準備操做(見5,大多數狀況下,不須要改漸變框)
調用onDraw()方法繪製視圖自己 (每一個View都須要重載該方法,ViewGroup不須要實現該方法)
調用dispatchDraw ()方法繪製子視圖(若是該View類型不爲ViewGroup,即不包含子視圖,不須要重載該方法)值得說明的是,ViewGroup類已經爲咱們重寫了dispatchDraw ()的功能實現,應用程序通常不須要重寫該方法,但能夠重載父類函數實現具體的功能。
####LinearLayout和RelativeLayout性能對比-百度

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

####優化自定義view百度-樂視-小米

爲了加速你的view,對於頻繁調用的方法,須要儘可能減小沒必要要的代碼。先從onDraw開始,須要特別注意不該該在這裏作內存分配的事情,由於它會致使GC,從而致使卡頓。在初始化或者動畫間隙期間作分配內存的動做。不要在動畫正在執行的時候作內存分配的事情。

你還須要儘量的減小onDraw被調用的次數,大多數時候致使onDraw都是由於調用了invalidate().所以請儘可能減小調用invaildate()的次數。若是可能的話,儘可能調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。

另一個很是耗時的操做是請求layout。任什麼時候候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每個view的大小。若是找到有衝突的值,它會須要從新計算好幾回。另外須要儘可能保持View的層級是扁平化的,這樣對提升效率頗有幫助。

若是你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操做。與內置的view不一樣,自定義的view能夠使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展現瞭如何繼承ViewGroup做爲自定義view的一部分。PieChart 有子views,可是它歷來不測量它們。而是根據他自身的layout法則,直接設置它們的大小。

####ContentProvider-樂視

http://blog.csdn.net/coder_pig/article/details/47858489

####Fragment生命週期

 

####volley解析-美團-樂視

http://a.codekk.com/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90

####Glide源碼解析

http://www.lightskystreet.com/2015/10/12/glide_source_analysis/ http://frodoking.github.io/2015/10/10/android-glide/

####Android設計模式

http://blog.csdn.net/bboyfeiyu/article/details/44563871

####架構設計-搜狐

 

http://www.tianmaying.com/tutorial/AndroidMVC

####Android屬性動畫特性-樂視-小米

若是你的需求中只須要對View進行移動、縮放、旋轉和淡入淡出操做,那麼補間動畫確實已經足夠健全了。可是很顯然,這些功能是不足以覆蓋全部的場景的,一旦咱們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操做,那麼補間動畫就不能再幫咱們忙了,也就是說它在功能和可擴展方面都有至關大的侷限性,那麼下面咱們就來看看補間動畫所不能勝任的場景。

注意上面我在介紹補間動畫的時候都有使用「對View進行操做」這樣的描述,沒錯,補間動畫是隻可以做用在View上的。也就是說,咱們能夠對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操做,可是若是咱們想要對一個非View的對象進行動畫操做,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會須要對一個非View的對象進行動畫操做呢?這裏我舉一個簡單的例子,好比說咱們有一個自定義的View,在這個View當中有一個Point對象用於管理座標,而後在onDraw()方法當中就是根據這個Point對象的座標值來進行繪製的。也就是說,若是咱們能夠對Point對象進行動畫操做,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具有這個功能的,這是它的第一個缺陷。

而後補間動畫還有一個缺陷,就是它只可以實現移動、縮放、旋轉和淡入淡出這四種動畫操做,那若是咱們但願能夠對View的背景色進行動態地改變呢?很遺憾,咱們只能靠本身去實現了。說白了,以前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。

最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?好比說,如今屏幕的左上角有一個按鈕,而後咱們經過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,由於實際上這個按鈕仍是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪製到了屏幕的右下角而已。

專題

性能優化

Android性能優化典範 - 第1季

Render Performance Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,若是每次渲染都成功,這樣就可以達到流暢的畫面所須要的60fps,爲了可以實現60fps,這意味着程序的大多數操做都必須在16ms內完成。咱們能夠經過一些工具來定位問題,好比能夠使用HierarchyViewer來查找Activity中的佈局是否過於複雜,也能夠使用手機設置裏面的開發者選項,打開Show GPU Overdraw等選項進行觀察。你還能夠使用TraceView來觀察CPU的執行狀況,更加快捷的找到性能瓶頸。
Understanding Overdraw Overdraw(過分繪製)描述的是屏幕上的某個像素在同一幀的時間內被繪製了屢次。在多層次的UI結構裏面,若是不可見的UI也在作繪製的操做,這就會致使某些像素區域被繪製了屢次。這就浪費大量的CPU以及GPU資源。Overdraw有時候是由於你的UI佈局存在大量重疊的部分,還有的時候是由於非必須的重疊背景。例如某個Activity有一個背景,而後裏面的Layout又有本身的背景,同時子View又分別有本身的背景。僅僅是經過移除非必須的背景圖片,這就可以減小大量的紅色Overdraw區域,增長藍色區域的佔比。這一措施可以顯著提高程序性能。
Understanding VSYNC Refresh Rate:表明了屏幕在一秒內刷新屏幕的次數,這取決於硬件的固定參數,例如60Hz。Frame Rate:表明了GPU在一秒內繪製操做的幀數,例如30fps,60fps。一般來講,幀率超過刷新頻率只是一種理想的情況,在超過60fps的狀況下,GPU所產生的幀數據會由於等待VSYNC的刷新信息而被Hold住,這樣可以保持每次刷新都有實際的新的數據能夠顯示。可是咱們遇到更多的狀況是幀率小於刷新頻率。
Tool:Profile GPU Rendering 性能問題如此的麻煩,幸虧咱們能夠有工具來進行調試。打開手機裏面的開發者選項,選擇Profile GPU Rendering,選中On screen as bars的選項。
Why 60fps? 咱們一般都會提到60fps與16ms,但是知道爲什麼會是以程序是否達到60fps來做爲App性能的衡量標準嗎?這是由於人眼與大腦之間的協做沒法感知超過60fps的畫面更新。開發app的性能目標就是保持60fps,這意味着每一幀你只有16ms=1000/60的時間來處理全部的任務。
Android, UI and the GPU 在Android裏面那些由主題所提供的資源,例如Bitmaps,Drawables都是一塊兒打包到統一的Texture紋理當中,而後再傳遞到GPU裏面,這意味着每次你須要使用這些資源的時候,都是直接從紋理裏面進行獲取渲染的。固然隨着UI組件的愈來愈豐富,有了更多演變的形態。例如顯示圖片的時候,須要先通過CPU的計算加載到內存中,而後傳遞給GPU進行渲染。文字的顯示更加複雜,須要先通過CPU換算成紋理,而後再交給GPU進行渲染,回到CPU繪製單個字符的時候,再從新引用通過GPU渲染的內容。動畫則是一個更加複雜的操做流程。爲了可以使得App流暢,咱們須要在每一幀16ms之內處理完全部的CPU與GPU計算,繪製,渲染等等操做。
Invalidations, Layouts, and Performance 任什麼時候候View中的繪製內容發生變化時,都會從新執行建立DisplayList,渲染DisplayList,更新到屏幕上等一系列操做。這個流程的表現性能取決於你的View的複雜程度,View的狀態變化以及渲染管道的執行性能。舉個例子,假設某個Button的大小須要增大到目前的兩倍,在增大Button大小以前,須要經過父View從新計算並擺放其餘子View的位置。修改View的大小會觸發整個HierarcyView的從新計算大小的操做。若是是修改View的位置則會觸發HierarchView從新計算其餘View的位置。若是佈局很複雜,這就會很容易致使嚴重的性能問題。咱們須要儘可能減小Overdraw。
Overdraw, Cliprect, QuickReject 咱們能夠經過canvas.clipRect()來幫助系統識別那些可見的區域。這個方法能夠指定一塊矩形區域,只有在這個區域內纔會被繪製,其餘的區域會被忽視。這個API能夠很好的幫助那些有多組重疊組件的自定義View來控制顯示的區域。同時clipRect方法還能夠幫助節約CPU與GPU資源,在clipRect區域以外的繪製指令都不會被執行,那些部份內容在矩形區域內的組件,仍然會獲得繪製。
Memory Churn and performance 執行GC操做的時候,全部線程的任何操做都會須要暫停,等待GC操做完成以後,其餘操做纔可以繼續運行。Memory Churn內存抖動,內存抖動是由於大量的對象被建立又在短期內立刻被釋放。瞬間產生大量的對象會嚴重佔用Young Generation的內存區域,當達到閥值,剩餘空間不夠的時候,也會觸發GC。即便每次分配的對象佔用了不多的內存,可是他們疊加在一塊兒會增長Heap的壓力,從而觸發更多其餘類型的GC。這個操做有可能會影響到幀率,並使得用戶感知到性能問題。
Garbage Collection in Android 原始JVM中的GC機制在Android中獲得了很大程度上的優化。Android裏面是一個三級Generation的內存模型,最近分配的對象會存放在Young Generation區域,當這個對象在這個區域停留的時間達到必定程度,它會被移動到Old Generation,最後到Permanent Generation區域。若是不當心在最小的for循環單元裏面執行了建立對象的操做,這將很容易引發GC並致使性能問題。經過Memory Monitor咱們能夠查看到內存的佔用狀況,每一次瞬間的內存下降都是由於此時發生了GC操做,若是在短期內發生大量的內存上漲與下降的事件,這說明頗有可能這裏有性能問題。咱們還能夠經過Heap and Allocation Tracker工具來查看此時內存中分配的到底有哪些對象。
Performance Cost of Memory Leaks 內存泄漏指的是那些程序再也不使用的對象沒法被GC識別,這樣就致使這個對象一直留在內存當中,佔用了寶貴的內存空間。顯然,這還使得每級Generation的內存區域可用空間變小,GC就會更容易被觸發,從而引發性能問題。
Memory Performance 一般來講,Android對GC作了大量的優化操做,雖然執行GC操做的時候會暫停其餘任務,但是大多數狀況下,GC操做仍是相對很安靜而且高效的。可是若是咱們對內存的使用不恰當,致使GC頻繁執行,這樣就會引發不小的性能問題。
Tool - Memory Monitor Android Studio中的Memory Monitor能夠很好的幫助咱們查看程序的內存使用狀況。
Battery Performance 咱們應該儘可能減小喚醒屏幕的次數與持續的時間,使用WakeLock來處理喚醒的問題,可以正確執行喚醒操做並根據設定及時關閉操做進入睡眠狀態。某些非必須立刻執行的操做,例如上傳歌曲,圖片處理等,能夠等到設備處於充電狀態或者電量充足的時候才進行。觸發網絡請求的操做,每次都會保持無線信號持續一段時間,咱們能夠把零散的網絡請求打包進行一次操做,避免過多的無線信號引發的電量消耗。關於網絡請求引發無線信號的電量消耗
Understanding Battery Drain on Android 使用WakeLock或者JobScheduler喚醒設備處理定時的任務以後,必定要及時讓設備回到初始狀態。每次喚醒無線信號進行數據傳遞,都會消耗不少電量,它比WiFi等操做更加的耗電
Battery Drain and WakeLocks 這正是JobScheduler API所作的事情。它會根據當前的狀況與任務,組合出理想的喚醒時間,例如等到正在充電或者鏈接到WiFi的時候,或者集中任務一塊兒執行。咱們能夠經過這個API實現不少免費的調度算法。
Android性能優化典範 - 第2季

Battery Drain and Networking 咱們能夠有針對性的把請求行爲捆綁起來,延遲到某個時刻統一發起請求。這部分主要會涉及到Prefetch(預取)與Compressed(壓縮)這兩個技術。對於Prefetch的使用,咱們須要預先判斷用戶在這次操做以後,後續零散的請求是否頗有可能會立刻被觸發,能夠把後面5分鐘有可能會使用到的零散請求都一次集中執行完畢。對於Compressed的使用,在上傳與下載數據以前,使用CPU對數據進行壓縮與解壓,能夠很大程度上減小網絡傳輸的時間。
Wear & Sensors 首先咱們須要儘可能使用Android平臺提供的既有運動數據,而不是本身去實現監聽採集數據,由於大多數Android Watch自身記錄Sensor數據的行爲是有通過作電量優化的。其次在Activity不須要監聽某些Sensor數據的時候須要儘快釋放監聽註冊。還有咱們須要儘可能控制更新的頻率,僅僅在須要刷新顯示數據的時候才觸發獲取最新數據的操做。另外咱們能夠針對Sensor的數據作批量處理,待數據累積必定次數或者某個程度的時候才更新到UI上。最後當Watch與Phone鏈接起來的時候,能夠把某些複雜操做的事情交給Phone來執行,Watch只須要等待返回的結果。
Smooth Android Wear Animation 在Android裏面一個相對操做比較繁重的事情是對Bitmap進行旋轉,縮放,裁剪等等。例如在一個圓形的鐘表圖上,咱們把時鐘的指針摳出來當作單獨的圖片進行旋轉會比旋轉一張完整的圓形圖的所造成的幀率要高56%。
Android Wear Data Batching 僅僅在真正須要刷新界面的時候才發出請求,儘可能把計算複雜操做的任務交給Phone來處理,Phone僅僅在數據發生變化的時候才通知到Wear,把零碎的數據請求捆綁一塊兒再進行操做。
Object Pools 使用對象池技術有不少好處,它能夠避免內存抖動,提高性能,可是在使用的時候有一些內容是須要特別注意的。一般狀況下,初始化的對象池裏面都是空白的,當使用某個對象的時候先去對象池查詢是否存在,若是不存在則建立這個對象而後加入對象池,可是咱們也能夠在程序剛啓動的時候就事先爲對象池填充一些即將要使用到的數據,這樣能夠在須要使用到這些對象的時候提供更快的首次加載速度,這種行爲就叫作預分配。使用對象池也有很差的一面,程序員須要手動管理這些對象的分配與釋放,因此咱們須要慎重地使用這項技術,避免發生對象的內存泄漏。爲了確保全部的對象可以正確被釋放,咱們須要保證加入對象池的對象和其餘外部對象沒有互相引用的關係。
To Index or Iterate? for index的方式有更好的效率,可是由於不一樣平臺編譯器優化各有差別,咱們最好仍是針對實際的方法作一下簡單的測量比較好,拿到數據以後,再選擇效率最高的那個方式。
The Magic of LRU Cache 使用LRU Cache可以顯著提高應用的性能,但是也須要注意LRU Cache中被淘汰對象的回收,否者會引發嚴重的內存泄露。
Using LINT for Performance Tips Lint已經集成到Android Studio中了,咱們能夠手動去觸發這個工具,點擊工具欄的Analysis -> Inspect Code,觸發以後,Lint會開始工做,並把結果輸出到底部的工具欄,咱們能夠逐個查看緣由並根據指示作相應的優化修改。
Hidden Cost of Transparency 一般來講,對於不透明的View,顯示它只須要渲染一次便可,但是若是這個View設置了alpha值,會至少須要渲染兩次。
Avoiding Allocations in onDraw() 首先onDraw()方法是執行在UI線程的,在UI線程儘可能避免作任何可能影響到性能的操做。雖然分配內存的操做並不須要花費太多系統資源,可是這並不意味着是免費無代價的。設備有必定的刷新頻率,致使View的onDraw方法會被頻繁的調用,若是onDraw方法效率低下,在頻繁刷新累積的效應下,效率低的問題會被擴大,而後會對性能有嚴重的影響。
Tool: Strict Mode Android提供了一個叫作Strict Mode的工具,咱們能夠經過手機設置裏面的開發者選項,打開Strict Mode選項,若是程序存在潛在的隱患,屏幕就會閃現紅色。咱們也能夠經過StrictMode API在代碼層面作細化的跟蹤,能夠設置StrictMode監聽那些潛在問題,出現問題時如何提醒開發者,能夠對屏幕閃紅色,也能夠輸出錯誤日誌。
Custom Views and Performance Useless calls to onDraw():咱們知道調用View.invalidate()會觸發View的重繪,有兩個原則須要遵照,第1個是僅僅在View的內容發生改變的時候纔去觸發invalidate方法,第2個是儘可能使用ClipRect等方法來提升繪製的性能。Useless pixels:減小繪製時沒必要要的繪製元素,對於那些不可見的元素,咱們須要儘可能避免重繪。Wasted CPU cycles:對於不在屏幕上的元素,能夠使用Canvas.quickReject把他們給剔除,避免浪費CPU資源。另外儘可能使用GPU來進行UI的渲染,這樣可以極大的提升程序的總體表現性能。
Batching Background Work Until Later 1.AlarmManager 使用AlarmManager設置定時任務,能夠選擇精確的間隔時間,也能夠選擇非精確時間做爲參數。除非程序有很強烈的須要使用精確的定時喚醒,否者必定要避免使用他,咱們應該儘可能使用非精確的方式。2.SyncAdapter 咱們能夠使用SyncAdapter爲應用添加設置帳戶,這樣在手機設置的帳戶列表裏面能夠找到咱們的應用。這種方式功能更多,可是實現起來比較複雜。咱們能夠從這裏看到官方的培訓課程:http://developer.android.com/training/sync-adapters/index.html 3.JobSchedulor 這是最簡單高效的方法,咱們能夠設置任務延遲的間隔,執行條件,還能夠增長重試機制。
Smaller Pixel Formats Android的Heap空間是不會自動作兼容壓縮的,意思就是若是Heap空間中的圖片被收回以後,這塊區域並不會和其餘已經回收過的區域作從新排序合併處理,那麼當一個更大的圖片須要放到heap以前,極可能找不到那麼大的連續空閒區域,那麼就會觸發GC,使得heap騰出一塊足以放下這張圖片的空閒區域,若是沒法騰出,就會發生OOM。
Smaller PNG Files 儘可能減小PNG圖片的大小是Android裏面很重要的一條規範。相比起JPEG,PNG可以提供更加清晰無損的圖片,可是PNG格式的圖片會更大,佔用更多的磁盤空間。究竟是使用PNG仍是JPEG,須要設計師仔細衡量,對於那些使用JPEG就能夠達到視覺效果的,能夠考慮採用JPEG便可。
Pre-scaling Bitmaps 對bitmap作縮放,這也是Android裏面最遇到的問題。對bitmap作縮放的意義很明顯,提示顯示性能,避免分配沒必要要的內存。Android提供了現成的bitmap縮放的API,叫作createScaledBitmap()
Re-using Bitmaps 使用inBitmap屬性能夠告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的bitmap會嘗試去使用以前那張bitmap在heap中所佔據的pixel data內存區域,而不是去問內存從新申請一塊區域來存放bitmap。利用這種特性,即便是上千張的圖片,也只會僅僅只須要佔用屏幕所可以顯示的圖片數量的內存大小。
The Performance Lifecycle Gather:收集數據,Insight:分析數據,Action:解決問題
Android性能優化典範 - 第3季

Fun with ArrayMaps 爲了解決HashMap更佔內存的弊端,Android提供了內存效率更高的ArrayMap。它內部使用兩個數組進行工做,其中一個數組記錄key hash事後的順序列表,另一個數組按key的順序記錄Key-Value值
Beware Autoboxing 有時候性能問題也多是由於那些不起眼的小細節引發的,例如在代碼中不經意的「自動裝箱」。咱們知道基礎數據類型的大小:boolean(8 bits), int(32 bits), float(32 bits),long(64 bits),爲了可以讓這些基礎數據類型在大多數Java容器中運做,會須要作一個autoboxing的操做,轉換成Boolean,Integer,Float等對象
SparseArray Family Ties 爲了不HashMap的autoboxing行爲,Android系統提供了SparseBoolMap,SparseIntMap,SparseLongMap,LongSparseMap等容器。
The price of ENUMs Android官方強烈建議不要在Android程序裏面使用到enum。
Trimming and Sharing Memory Android系統提供了一些回調來通知應用的內存使用狀況,一般來講,當全部的background應用都被kill掉的時候,forground應用會收到onLowMemory()的回調。在這種狀況下,須要儘快釋放當前應用的非必須內存資源,從而確保系統可以穩定繼續運行。Android系統還提供了onTrimMemory()的回調,當系統內存達到某些條件的時候,全部正在運行的應用都會收到這個回調
DO NOT LEAK VIEWS 避免使用異步回調,避免使用Static對象,避免把View添加到沒有清除機制的容器裏面
Location & Battery Drain 其中存在的一個優化點是,咱們能夠經過判斷返回的位置信息是否相同,從而決定設置下次的更新間隔是否增長一倍,經過這種方式能夠減小電量的消耗
Double Layout Taxation 佈局中的任何一個View一旦發生一些屬性變化,均可能引發很大的連鎖反應。例如某個button的大小忽然增長一倍,有可能會致使兄弟視圖的位置變化,也有可能致使父視圖的大小發生改變。當大量的layout()操做被頻繁調用執行的時候,就極可能引發丟幀的現象。
Network Performance 101 減小移動網絡被激活的時間與次數,壓縮傳輸數據
Effective Network Batching 發起網絡請求與接收返回數據都是比較耗電的,在網絡硬件模塊被激活以後,會繼續保持幾十秒的電量消耗,直到沒有新的網絡操做行爲以後,纔會進入休眠狀態。前面一個段落介紹了使用Batching的技術來捆綁網絡請求,從而達到減小網絡請求的頻率。那麼如何實現Batching技術呢?一般來講,咱們能夠會把那些發出的網絡請求,先暫存到一個PendingQueue裏面,等到條件合適的時候再觸發Queue裏面的網絡請求。
Optimizing Network Request Frequencies 前面的段落已經提到了應該減小網絡請求的頻率,這是爲了減小電量的消耗。咱們能夠使用Batching,Prefetching的技術來避免頻繁的網絡請求。Google提供了GCMNetworkManager來幫助開發者實現那些功能,經過提供的API,咱們能夠選擇在接入WiFi,開始充電,等待移動網絡被激活等條件下再次激活網絡請求。
Effective Prefetching 相似上面的狀況會頻繁觸發網絡請求,可是若是咱們可以預先請求後續可能會使用到網絡資源,避免頻繁的觸發網絡請求,這樣就可以顯著的減小電量的消耗。但是預先獲取多少數據量是很值得考量的,由於若是預取數據量偏少,就起不到減小頻繁請求的做用,但是若是預取數據過多,就會形成資源的浪費。
Android性能優化典範 - 第4季

Cachematters for networking 想要使得Android系統上的網絡訪問操做更加的高效就必須作好網絡數據的緩存。這是提升網絡訪問性能最基礎的步驟之一。從手機的緩存中直接讀取數據確定比從網絡上獲取數據要更加的便捷高效,特別是對於那些會被頻繁訪問到的數據,須要把這些數據緩存到設備上,以便更加快速的進行訪問。
Optimizing Network Request Frequencies 首先咱們要對網絡行爲進行分類,區分須要當即更新數據的行爲和其餘能夠進行延遲的更新行爲,爲不一樣的場景進行差別化處理。其次要避免客戶端對服務器的輪詢操做,這樣會浪費不少的電量與帶寬流量。解決這個問題,咱們能夠使用Google Cloud Message來對更新的數據進行推送。而後在某些必須作同步的場景下,須要避免使用固定的間隔頻率來進行更新操做,咱們應該在返回的數據無更新的時候,使用雙倍的間隔時間來進行下一次同步。最後更進一步,咱們還能夠經過判斷當前設備的狀態來決定同步的頻率,例如判斷設備處於休眠,運動等不一樣的狀態設計各自不一樣時間間隔的同步頻率。
Effective Prefetching 到底預取多少才比較合適呢?一個比較普適的規則是,在3G網絡下能夠預取1-5Mb的數據量,或者是按照提早預期後續1-2分鐘的數據做爲基線標準。在實際的操做當中,咱們還須要考慮當前的網絡速度來決定預取的數據量,例如在一樣的時間下,4G網絡能夠獲取到12張圖片的數據,而2G網絡則只能拿到3張圖片的數據。因此,咱們還須要把當前的網絡環境狀況添加到設計預取數據量的策略當中去。判斷當前設備的狀態與網絡狀況,能夠使用前面提到過的GCMNetworkManager。
Adapting to Latency 一個典型的網絡操做行爲,一般包含如下幾個步驟:首先手機端發起網絡請求,到達網絡服務運營商的基站,再轉移到服務提供者的服務器上,通過解碼以後,接着訪問本地的存儲數據庫,獲取到數據以後,進行編碼,最後按照原來傳遞的路徑逐層返回。常來講,咱們能夠把網絡請求延遲劃分爲三檔:例如把網絡延遲小於60ms的劃分爲GOOD,大於220ms的劃分爲BAD,介於二者之間的劃分爲OK(這裏的60ms,220ms會須要根據不一樣的場景提早進行預算推測)。
Minimizing Asset Payload 爲了可以減少網絡傳輸的數據量,咱們須要對傳輸的數據作壓縮的處理,這樣可以提升網絡操做的性能。首先須要作的是減小圖片的大小,其次須要作的是減小序列化數據的大小。
Service Performance Patterns Service是Android程序裏面最經常使用的基礎組件之一,可是使用Service很容易引發電量的過分消耗以及系統資源的未及時釋放。避免錯誤的使用Service,例如咱們不該該使用Service來監聽某些事件的變化,不該該搞一個Service在後臺對服務器不斷的進行輪詢(應該使用Google Cloud Messaging)。若是已經事先知道Service裏面的任務應該執行在後臺線程(非默認的主線程)的時候,咱們應該使用IntentService或者結合HanderThread,AsycnTask Loader實現的Service。
Removing unused code Android爲咱們提供了Proguard的工具來幫助應用程序對代碼進行瘦身,優化,混淆的處理。它會幫助移除那些沒有使用到的代碼,還能夠對類名,方法名進行混淆處理以免程序被反編譯。
Removing unused resources 所幸的是,咱們能夠使用Gradle來幫助咱們分析代碼,分析引用的資源,對於那些沒有被引用到的資源,會在編譯階段被排除在APK安裝包以外,要實現這個功能,對咱們來講僅僅只須要在build.gradle文件中配置shrinkResource爲true就行了
Perf Theory: Caching 當咱們討論性能優化的時候,緩存是最多見最有效的策略之一。不管是爲了提升CPU的計算速度仍是提升數據的訪問速度,在絕大多數的場景下,咱們都會使用到緩存。
Perf Theory: Approximation(近似法) 例如使用一張比較接近實際大小的圖片來替代原圖,換取更快的加載速度。因此對於那些對計算結果要求不須要十分精確的場景,咱們能夠使用近似法則來提升程序的性能。
Perf Theory: Culling(遴選,挑選) 一個提升性能的方法是逐步對數據進行過濾篩選,減少搜索的數據集,以此提升程序的執行性能。例如咱們須要搜索到居住在某個地方,年齡是多少,符合某些特定條件的候選人,就能夠經過逐層過濾篩選的方式來提升後續搜索的執行效率。
Perf Theory: Threading 使用多線程併發處理任務,從某種程度上能夠快速提升程序的執行性能。對於Android程序來講,主線程一般也成爲UI線程,須要處理UI的渲染,響應用戶的操做等等。
Perf Theory: Batching 網絡請求的批量執行是另一個比較適合說明batching使用場景的例子,由於每次發起網絡請求都相對來講比較耗時耗電,若是可以作到批量一塊兒執行,能夠大大的減小電量的消耗。
Serialization performance 數據序列化的行爲可能發生在數據傳遞過程當中的任何階段,例如網絡傳輸,不一樣進程間數據傳遞,不一樣類之間的參數傳遞,把數據存儲到磁盤上等等。一般狀況下,咱們會把那些須要序列化的類實現Serializable接口(以下圖所示),可是這種傳統的作法效率不高,實施的過程會消耗更多的內存。可是咱們若是使用GSON庫來處理這個序列化的問題,不只僅執行速度更快,內存的使用效率也更高。Android的XML佈局文件會在編譯的階段被轉換成更加複雜的格式,具有更加高效的執行性能與更高的內存使用效率。
Smaller Serialized Data 數據呈現的順序以及結構會對序列化以後的空間產生不小的影響。
Caching UI data 緩存UI界面上的數據,能夠採用方案有存儲到文件系統,Preference,SQLite等等,作了緩存以後,這樣就能夠在請求數據返回結果以前,呈現給用戶舊的數據,而不是使用正在加載的方式讓用戶什麼數據都看不到,固然在請求網絡最新數據的過程當中,須要有正在刷新的提示。至於到底選擇哪一個方案來對數據進行緩存,就須要根據具體狀況來作選擇了。
CPU Frequency Scaling 調節CPU的頻率會執行的性能產生較大的影響,爲了最大化的延長設備的續航時間,系統會動態調整CPU的頻率,頻率越高執行代碼的速度天然就越快。咱們能夠使用Systrace工具來導出CPU的執行狀況,以便幫助定位性能問題。
Android性能優化典範 - 第5季

Threading Performance AsyncTask: 爲UI線程與工做線程之間進行快速的切換提供一種簡單便捷的機制。適用於當下當即須要啓動,可是異步執行的生命週期短暫的使用場景。HandlerThread: 爲某些回調方法或者等待某些任務的執行設置一個專屬的線程,並提供線程任務的調度機制。ThreadPool: 把任務分解成不一樣的單元,分發到各個不一樣的線程上,進行同時併發處理。IntentService: 適合於執行由UI觸發的後臺Service任務,並能夠把後臺任務執行的狀況經過必定的機制反饋給UI。
Understanding Android Threading 一般來講,一個線程須要經歷三個生命階段:開始,執行,結束。線程會在任務執行完畢以後結束,那麼爲了確保線程的存活,咱們會在執行階段給線程賦予不一樣的任務,而後在裏面添加退出的條件從而確保任務可以執行完畢後退出。
Memory & Threading 不要在任何非UI線程裏面去持有UI對象的引用。系統爲了確保全部的UI對象都只會被UI線程所進行建立,更新,銷燬的操做,特意設計了對應的工做機制(當Activity被銷燬的時候,由該Activity所觸發的非UI線程都將沒法對UI對象進行操做,否者就會拋出程序執行異常的錯誤)來防止UI對象被錯誤的使用。
Good AsyncTask Hunting AsyncTask雖然提供了一種簡單便捷的異步機制,可是咱們仍是頗有必要特別關注到他的缺點,避免出現由於使用錯誤而致使的嚴重系統性能問題。
Getting a HandlerThread HandlerThread比較合適處理那些在工做線程執行,須要花費時間偏長的任務。咱們只須要把任務發送給HandlerThread,而後就只須要等待任務執行結束的時候通知返回到主線程就行了。另外很重要的一點是,一旦咱們使用了HandlerThread,須要特別注意給HandlerThread設置不一樣的線程優先級,CPU會根據設置的不一樣線程優先級對全部的線程進行調度優化。
Swimming in Threadpools 線程池適合用在把任務進行分解,併發進行執行的場景。一般來講,系統裏面會針對不一樣的任務設置一個單獨的守護線程用來專門處理這項任務。
The Zen of IntentService 默認的Service是執行在主線程的,但是一般狀況下,這很容易影響到程序的繪製性能(搶佔了主線程的資源)。除了前面介紹過的AsyncTask與HandlerThread,咱們還能夠選擇使用IntentService來實現異步操做。IntentService繼承自普通Service同時又在內部建立了一個HandlerThread,在onHandlerIntent()的回調裏面處理扔到IntentService的任務。因此IntentService就不只僅具有了異步線程的特性,還同時保留了Service不受主頁面生命週期影響的特色。
Threading and Loaders 當啓動工做線程的Activity被銷燬的時候,咱們應該作點什麼呢?爲了方便的控制工做線程的啓動與結束,Android爲咱們引入了Loader來解決這個問題。咱們知道Activity有可能由於用戶的主動切換而頻繁的被建立與銷燬,也有多是由於相似屏幕發生旋轉等被動緣由而銷燬再重建。在Activity不停的建立與銷燬的過程中,頗有可能由於工做線程持有Activity的View而致使內存泄漏(由於工做線程極可能持有View的強引用,另外工做線程的生命週期還沒法保證和Activity的生命週期一致,這樣就容易發生內存泄漏了)。除了可能引發內存泄漏以外,在Activity被銷燬以後,工做線程還繼續更新視圖是沒有意義的,由於此時視圖已經不在界面上顯示了。
The Importance of Thread Priority 在Android系統裏面,咱們能夠經過android.os.Process.setThreadPriority(int)設置線程的優先級,參數範圍從-20到24,數值越小優先級越高。Android系統還爲咱們提供瞭如下的一些預設值,咱們能夠經過給不一樣的工做線程設置不一樣數值的優先級來達到更細粒度的控制。
Profile GPU Rendering : M Update 從Android M系統開始,系統更新了GPU Profiling的工具來幫助咱們定位UI的渲染性能問題。早期的CPU Profiling工具只能粗略的顯示出Process,Execute,Update三大步驟的時間耗費狀況。
官方性能優化系列教程

架構分析

MVVM

MVP

阿里面試題

進程間通訊方式

經過Intent在Activity、Service或BroadcastReceiver間進行進程間通訊,可經過Intent傳遞數據
AIDL方式
Messenger方式
利用ContentProvider
Socket方式
基於文件共享的方式
什麼是協程

咱們知道多個線程相對獨立,有本身的上下文,切換受系統控制;而協程也相對獨立,有本身的上下文,可是其切換由本身控制,由當前協程切換到其餘協程由當前協程來控制。 ?

內存泄露是怎麼回事

由忘記釋放分配的內存致使的

程序計數器,引到了邏輯地址(虛地址)和物理地址及其映射關係

虛擬機中的程序計數器是Java運行時數據區中的一小塊內存區域,可是它的功能和一般的程序計數器是相似的,它指向虛擬機正在執行字節碼指令的地址。具體點兒說,當虛擬機執行的方法不是native的時,程序計數器指向虛擬機正在執行字節碼指令的地址;當虛擬機執行的方法是native的時,程序計數器中的值是未定義的。另外,程序計數器是線程私有的,也就是說,每個線程都擁有僅屬於本身的程序計數器。

數組和鏈表的區別

數組是將元素在內存中連續存放,因爲每一個元素佔用內存相同,能夠經過下標迅速訪問數組中任何元素。可是若是要在數組中增長一個元素,須要移動大量元素,在內存中空出一個元素的空間,而後將要增長的元素放在其中。一樣的道理,若是想刪除一個元素,一樣須要移動大量元素去填掉被移動的元素。若是應用須要快速訪問數據,不多或不插入和刪除元素,就應該用數組。

鏈表剛好相反,鏈表中的元素在內存中不是順序存儲的,而是經過存在元素中的指針聯繫到一塊兒。好比:上一個元素有個指針指到下一個元素,以此類推,直到最後一個元素。若是要訪問鏈表中一個元素,須要從第一個元素開始,一直找到須要的元素位置。可是增長和刪除一個元素對於鏈表數據結構就很是簡單了,只要修改元素中的指針就能夠了。若是應用須要常常插入和刪除元素你就須要用鏈表數據結構了。

二叉樹的深度優先遍歷和廣度優先遍歷的具體實現

http://www.i3geek.com/archives/794

堆的結構

年輕代(Young Generation)、年老代(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java類的類信息,與垃圾收集要收集的Java對象關係 不大。年輕代和年老代的劃分是對垃 圾收集影響比較大的。

bitmap對象的理解

http://blog.csdn.net/angel1hao/article/details/51890938

什麼是深拷貝和淺拷

淺拷貝:使用一個已知實例對新建立實例的成員變量逐個賦值,這個方式被稱爲淺拷貝。 深拷貝:當一個類的拷貝構造方法,不只要複製對象的全部非引用成員變量值,還要爲引用類型的成員變量建立新的實例,而且初始化爲形式參數實例值。這個方式稱爲深拷貝

對象鎖和類鎖是否會互相影響

對象鎖:Java的全部對象都含有1個互斥鎖,這個鎖由JVM自動獲取和釋放。線程進入synchronized方法的時候獲取該對象的鎖,固然若是已經有線程獲取了這個對象的鎖,那麼當前線程會等待;synchronized方法正常返回或者拋異常而終止,JVM會自動釋放對象鎖。這裏也體現了用synchronized來加鎖的1個好處,方法拋異常的時候,鎖仍然能夠由JVM來自動釋放。 類鎖: 對象鎖是用來控制實例方法之間的同步,類鎖是用來控制靜態方法(或靜態變量互斥體)之間的同步。其實類鎖只是一個概念上的東西,並非真實存在的,它只是用來幫助咱們理解鎖定實例方法和靜態方法的區別的。咱們都知道,java類可能會有不少個對象,可是隻有1個Class對象,也就是說類的不一樣實例之間共享該類的Class對象。Class對象其實也僅僅是1個java對象,只不過有點特殊而已。因爲每一個java對象都有1個互斥鎖,而類的靜態方法是須要Class對象。因此所謂的類鎖,不過是Class對象的鎖而已。獲取類的Class對象有好幾種,最簡單的就是MyClass.class的方式。 類鎖和對象鎖不是同1個東西,一個是類的Class對象的鎖,一個是類的實例的鎖。也就是說:1個線程訪問靜態synchronized的時候,容許另外一個線程訪問對象的實例synchronized方法。反過來也是成立的,由於他們須要的鎖是不一樣的。

looper架構

http://wangkuiwu.github.io/2014/08/26/MessageQueue/

自定義控件原理

http://www.jianshu.com/p/988326f9c8a3

binder工做原理

Binder是客戶端和服務端進行通信的媒介

ActivityThread,Ams,Wms的工做原理

ActivityThread: 運行在應用進程的主線程上,響應 ActivityManangerService 啓動、暫停Activity,廣播接收等消息。 ams:統一調度各應用程序的Activity、內存管理、進程管理

Java中final,finally,finalize的區別

final 用於聲明屬性,方法和類, 分別表示屬性不可變, 方法不可覆蓋, 類不可繼承.?
finally 是異常處理語句結構的一部分,表示老是執行.?
finalize 是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,能夠覆蓋此方法提供垃圾收集時的其餘資源回收,例如關閉文件等. JVM不保證此方法總被調用.
一個文件中有100萬個整數,由空格分開,在程序中判斷用戶輸入的整數是否在此文件中。說出最優的方法

兩個進程同時要求寫或者讀,能不能實現?如何防止進程的同步?

volatile 的意義?

防止CPU指令重排序

單例

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;
}
}
Given a string, determine if it is a palindrome(迴文,若是不清楚,按字面意思腦補下), considering only alphanumeric characters and ignoring cases.

For example, "A man, a plan, a canal: Panama" is a palindrome. "race a car" is not a palindrome.

Note: Have you consider that the string might be empty? This is a good question to ask during an interview. For the purpose of this problem, we define empty string as valid palindrome.

public boolean isPalindrome(String palindrome){
char[] palindromes = palidrome.toCharArray();
if(palindromes.lengh == 0){
return true
}
Arraylist<Char> temp = new Arraylist();
for(int i=0;i<palindromes.length;i++){
if((palindromes[i]>'a' && palindromes[i]<'z')||palindromes[i]>'A' && palindromes[i]<'Z')){
temp.add(palindromes[i].toLowerCase());
}
}
for(int i=0;i<temp.size()/2;i++){
if(temp.get(i) != temp.get(temp.size()-i)){
//
return false;
}
}
return true;
}
燒一根不均勻的繩,從頭燒到尾總共須要1個小時。如今有若干條材質相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢

用兩根繩子,一個繩子兩頭燒,一個一頭燒。

騰訊

2000萬個整數,找出第五十大的數字?

冒泡、選擇、建堆

從網絡加載一個10M的圖片,說下注意事項

圖片緩存、異常恢復、質量壓縮

自定義View注意事項

渲染幀率、內存

項目中經常使用的設計模式

單例、觀察者、適配器、建造者。。

JVM的理解

http://www.infoq.com/cn/articles/java-memory-model-1

相關文章
相關標籤/搜索