2017安卓面試題大全
JAVA 相關
1.靜態內部類、內部類、匿名內部類,為什麼內部類會持有外部類的引用?持有的引用是this?還是其它?
靜態內部類:使用static修飾的內部類
內部類:就是在某個類的內部又定義了一個類,內部類所嵌入的類稱為外部類
匿名內部類:使用new生成的內部類
因為內部類的產生依賴於外部類,持有的引用是類名.this
2.Java中try catch finally的執行順序
先執行try中程式碼,如果發生異常執行catch中程式碼,最後一定會執行finally中程式碼
3.equals與==的區別:
==是判斷兩個變數或例項是不是指向同一個記憶體空間 equals是判斷兩個變數或例項所指向的記憶體空間的值是不是相
4.Object有哪些公用方法?
方法equals測試的是兩個物件是否相等
方法clone進行物件拷貝
方法getClass返回和當前物件相關的Class物件
方法notify,notifyall,wait都是用來對給定物件進行執行緒同步的
5.String、StringBuffer與StringBuilder的區別
String 型別和 StringBuffer 型別的主要效能區別其實在於 String 是不可變的物件 StringBuffer和StringBuilder底層是 char[]陣列實現的 StringBuffer是執行緒安全的,而StringBuilder是執行緒不安全的
6.Java的四種引用的區別
強引用:如果一個物件具有強引用,它就不會被垃圾回收器回收。即使當前記憶體空間不足,JVM 也不會回收它,而是丟擲 OutOfMemoryError 錯誤,使程式異常終止。如果想中斷強引用和某個物件之間的關聯,可以顯式地將引用賦值為null,這樣一來的話,JVM在合適的時間就會回收該物件
軟引用:在使用軟引用時,如果記憶體的空間足夠,軟引用就能繼續被使用,而不會被垃圾回收器回收,只有在記憶體不足時,軟引用才會被垃圾回收器回收。
弱引用:具有弱引用的物件擁有的生命週期更短暫。因為當 JVM 進行垃圾回收,一旦發現弱引用物件,無論當前記憶體空間是否充足,都會將弱引用回收。不過由於垃圾回收器是一個優先順序較低的執行緒,所以並不一定能迅速發現弱引用物件
虛引用:顧名思義,就是形同虛設,如果一個物件僅持有虛引用,那麼它相當於沒有引用,在任何時候都可能被垃圾回收器回收。
7.介紹垃圾回收機制
標記回收法:遍歷物件圖並且記錄可到達的物件,以便刪除不可到達的物件,一般使用單執行緒工作並且可能產生記憶體碎片
標記-壓縮回收法:前期與第一種方法相同,只是多了一步,將所有的存活物件壓縮到記憶體的一端,這樣記憶體碎片就可以合成一大塊可再利用的記憶體區域,提高了記憶體利用率
複製回收法:把現有記憶體空間分成兩部分,gc執行時,它把可到達物件複製到另一半空間,再清空正在使用的空間的全部物件。這種方法適用於短生存期的物件,持續複製長生存期的物件則導致效率降低。
分代回收發:把記憶體空間分為兩個或者多個域,如年輕代和老年代,年輕代的特點是物件會很快被回收,因此在年輕代使用效率比較高的演算法。當一個物件經過幾次回收後依然存活,物件就會被放入稱為老年的記憶體空間,老年代則採取標記-壓縮演算法
集合、資料結構相關
1.你用過哪些集合類
資料結構中用於儲存資料的有哪些
陣列
陣列儲存區間是連續的,佔用記憶體嚴重,故空間複雜的很大。但陣列的二分查詢時間複雜度小,為O(1);陣列的特點是:定址容易,插入和刪除困難;
連結串列
連結串列儲存區間離散,佔用記憶體比較寬鬆,故空間複雜度很小,但時間複雜度很大,達O(N)。連結串列的特點是:定址困難,插入和刪除容易。
2.說說hashMap是怎樣實現的
雜湊表:由陣列+連結串列組成的
當我們往HashMap中put元素的時候,先根據key的hashCode重新計算hash值,根據hash值得到這個元素在陣列中的位置(即下標),如果陣列該位置上已經存放有其他元素了,那麼在這個位置上的元素將以連結串列的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。如果陣列該位置上沒有元素,就直接將該元素放到此陣列中的該位置上。
3.ArrayList,LinkedList的區別
ArrayList是實現了基於動態陣列的資料結構,LinkedList基於連結串列的資料結構。
對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。
對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。
4.ArrayList和Vector的主要區別是什麼?
ArrayList 和Vector底層是採用陣列方式儲存資料
Vector:
執行緒同步
當Vector中的元素超過它的初始大小時,Vector會將它的容量翻倍,
ArrayList:
執行緒不同步,但效能很好
當ArrayList中的元素超過它的初始大小時,ArrayList只增加50%的大小
5.HashMap和 HashTable 的區別:
HashTable比較老,是基於Dictionary 類實現的,HashTable 則是基於 Map介面實現的
HashTable 是執行緒安全的, HashMap 則是執行緒不安全的
HashMap可以讓你將空值作為一個表的條目的key或value
演算法相關
1.排序演算法和穩定性,快排什麼時候情況最壞?
2.給最外層的rootview,把這個根檢視下的全部button背景設定成紅色,手寫程式碼,不許用遞迴
演算法原理:
Android的view檢視是按樹形結構分佈,所以按樹形結構遍歷
迴圈判斷每一層的ViewGroup元素,將其入棧;否則判斷當前view是否是Button類例項,是則改寫背景色
當前ViewGroup檢查childView完成後,判斷棧是否非空,取出棧頂元素ViewGroup重複步驟2直至棧為空。
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void
changeAllBtnBGColor(View view, int
color) {
if
(view == null || !(view
instanceof ViewGroup))
return ;
Stack m = new
Stack<>();
while
(view != null ) {
ViewGroup tmpGroup = (ViewGroup) view;
int
count = tmpGroup.getChildCount();
for
( int i =
0 ; i < count; i++) { View child = tmpGroup.getChildAt(i);
if
(child instanceof
ViewGroup) m.add(child);
else
if (child instanceof
Button) { child.setBackgroundColor(color);
} }
if
(m.isEmpty()) break ;
else
view = m.pop();
}
}
|
Thread、AsynTask相關
1.wait()和sleep()的區別sleep來自Thread類,和wait來自Object類
呼叫sleep()方法的過程中,執行緒不會釋放物件鎖。而 呼叫 wait 方法執行緒會釋放物件鎖
sleep睡眠後不出讓系統資源,wait讓出系統資源其他執行緒可以佔用CPU
sleep(milliseconds)需要指定一個睡眠時間,時間一到會自動喚醒
2.若Activity已經銷燬,此時AsynTask執行完並且返回結果,會報異常嗎?
當一個App旋轉時,整個Activity會被銷燬和重建。當Activity重啟時,AsyncTask中對該Activity的引用是無效的,因此onPostExecute()就不會起作用,若AsynTask正在執行,折會報 view not attached to window manager 異常
同樣也是生命週期的問題,在 Activity 的onDestory()方法中呼叫Asyntask.cancal方法,讓二者的生命週期同步
3.Activity銷燬但Task如果沒有銷燬掉,當Activity重啟時這個AsyncTask該如何解決?
還是螢幕旋轉這個例子,在重建Activity的時候,會回掉Activity.onRetainNonConfigurationInstance()重新傳遞一個新的物件給AsyncTask,完成引用的更新
4.Android 執行緒間通訊有哪幾種方式(重要)
共享記憶體(變數);
檔案,資料庫;
Handler;
Java 裡的 wait(),notify(),notifyAll()
5.請介紹下 AsyncTask的內部實現,適用的場景是
AsyncTask 內部也是 Handler 機制來完成的,只不過 Android 提供了執行框架來提供執行緒池來
執行相應地任務,因為執行緒池的大小問題,所以 AsyncTask 只應該用來執行耗時時間較短的任務,
比如 HTTP 請求,大規模的下載和資料庫的更改不適用於 AsyncTask,因為會導致執行緒池堵塞,沒有
執行緒來執行其他的任務,導致的情形是會發生 AsyncTask 根本執行不了的問題。
網路相關
1.TCP三次握手
2.為什麼TCP是可靠的,UDP早不可靠的?為什麼UDP比TCP快?
TCP/IP協議高,因為其擁有三次握手雙向機制,這一機制保證校驗了資料,保證了他的可靠性。
UDP就沒有了,udp資訊發出後,不驗證是否到達對方,所以不可靠。
但是就速度來說,還是UDP協議更高,畢竟其無需重複返回驗證,只是一次性的
3.http協議瞭解多少,說說裡面的協議頭部有哪些欄位?
http(超文字傳輸協議)是一個基於請求與響應模式的、無狀態的、應用層的協議;http請求由三部分組成,分別是:請求行、訊息報頭、請求正文。
HTTP訊息報頭包括普通報頭、請求報頭、響應報頭、實體報頭
4.https瞭解多少
HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL。
5.談談 HTTP 中Get 和 Post 方法的區別
GET - 從指定的伺服器中獲取資料,明文傳送內容
POST - 提交資料給指定的伺服器處理
1. POST請求不能被快取下來
2. POST請求不會儲存在瀏覽器瀏覽記錄中
3. 以POST請求的URL無法儲存為瀏覽器書籤
4. POST請求沒有長度限制
6.推送心跳包是TCP包還是UDP包或者HTTP包
心跳包的實現是呼叫了socket.sendUrgentData(0xFF)這句程式碼實現的,所以,當然是TCP包。
7.如何實現檔案斷點上傳
在 Android 中上傳檔案可以採用 HTTP 方式,也可以採用 Socket 方式,但是 HTTP 方式不能上傳
大檔案,這裡介紹一種通過 Socket 方式來進行斷點續傳的方式,服務端會記錄下檔案的上傳進度,
當某一次上傳過程意外終止後,下一次可以繼續上傳,這裡用到的其實還是 J2SE 裡的知識。
這個上傳程式的原理是:客戶端第一次上傳時向服務端傳送
“Content-Length=35;filename=WinRAR_3.90_SC.exe;sourceid=“這種格式的字串,服務端
收到後會查詢該檔案是否有上傳記錄,如果有就返回已經上傳的位置,否則返回新生成的 sourceid
以及 position 為 0,類似 sourceid=2324838389;position=0“這樣的字串,客戶端收到返回後
的字串後再從指定的位置開始上傳檔案。
Fragment相關
1.Fragment 如何實現類似 Activity 棧的壓棧和出棧效果的?
Fragment 的事物管理器內部維持了一個雙向連結串列結構,該結構可以記錄我們每次 add 的
Fragment 和 replace 的 Fragment,然後當我們點選 back 按鈕的時候會自動幫我們實現退棧操作。
2.Fragment 在你們專案中的使用
Fragment 是 android3.0 以後引入的的概念,做區域性內容更新更方便,原來為了到達這一點要
把多個佈局放到一個 activity 裡面,現在可以用多 Fragment 來代替,只有在需要的時候才載入
Fragment,提高效能。
Fragment 的好處:
1. Fragment 可以使你能夠將 activity 分離成多個可重用的元件,每個都有它自己的生命週期和
UI。
2. Fragment 可以輕鬆得建立動態靈活的 UI 設計,可以適應於不同的螢幕尺寸。從手機到平板電
腦。
3. Fragment 是一個獨立的模組,緊緊地與 activity 繫結在一起。可以執行中動態地移除、加入、
交換等。
4. Fragment 提供一個新的方式讓你在不同的安卓裝置上統一你的 UI。
5. Fragment 解決 Activity 間的切換不流暢,輕量切換。
6. Fragment 替代 TabActivity 做導航,效能更好。
7. Fragment 在 4.2.版本中新增巢狀 fragment 使用方法,能夠生成更好的介面效果
3.如何切換 fragement,不重新例項化
正確的切換方式是 add(),切換時 hide(),add()另一個 Fragment;再次切換時,只需 hide()當前,
show()另一個
四大元件相關
1.Activity和Fragment生命週期有哪些?
Activity——onCreate->onStart->onResume->onPause->onStop->onDestroy
Fragment——onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach
2.廣播的兩種註冊方式及有什麼區別
3.記憶體不足時,怎麼保持Activity的一些狀態,在哪個方法裡面做具體操作?
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:記憶體不足、使用者直接按Home鍵)由系統銷燬一個Activity,onSaveInstanceState() 會被呼叫。但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被呼叫。除非該activity是被使用者主動銷燬的,通常onSaveInstanceState()只適合用於儲存一些臨時性的狀態,而onPause()適合用於資料的持久化儲存。
4.啟動service的兩種方法?有什麼區別?
一種是startService(),另一種是bindService()。這兩者的區別是第一種方式呼叫者開啟了服務,即會與服務失去聯絡,兩者沒有關聯。即使訪問者退出了,服務仍在執行。如需解除服務必須顯式的呼叫stopService方法。主要用於呼叫者與服務沒有互動的情況下,也就是呼叫者不需要獲取服務裡的業務方法。比如電話錄音。而後者呼叫者與服務繫結在一起的。當呼叫者退出的時候,服務也隨之退出。用於需要與服務互動。
5.Android中的Context, Activity,Appliction有什麼區別?
相同:Activity和Application都是Context的子類。
Context從字面上理解就是上下文的意思,在實際應用中它也確實是起到了管理上下文環境中各個引數和變數的總用,方便我們可以簡單的訪問到各種資源。
不同:維護的生命週期不同。 Context維護的是當前的Activity的生命週期,Application維護的是整個專案的生命週期。
使用context的時候,小心記憶體洩露,防止記憶體洩露,注意一下幾個方面:
1. 不要讓生命週期長的物件引用activity context,即保證引用activity的物件要與activity本身生命週期是一樣的。
2. 對於生命週期長的物件,可以使用application,context。
3. 避免非靜態的內部類,儘量使用靜態類,避免生命週期問題,注意內部類對外部物件引用導致的生命週期變化。
6.Context是什麼?
它描述的是一個應用程式環境的資訊,即上下文。
該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實現類(ContextIml)。
通過它我們可以獲取應用程式的資源和類,也包括一些應用級別操作,例如:啟動一個Activity,傳送廣播,接受Intent,資訊,等。
7.Service 是否在 main thread 中執行, service 裡面是否能執行耗時的操
作?
預設情況,如果沒有顯示的指 servic 所執行的程序, Service 和 activity 是執行在當前 app 所在進
程的 main thread(UI 主執行緒)裡面。
service 裡面不能執行耗時的操作(網路請求,拷貝資料庫,大檔案 )
特殊情況 ,可以在清單檔案配置 service 執行所在的程序 ,讓 service 在另外的程序中執行
1 2 3 4 5 |
<service
android:name= "com.baidu.location.f"
android:enabled= "true"
android:process= ":remote"
>
</service>
|
8.Activity 怎麼和 Service 繫結,怎麼在 Activity 中啟動自己對應的
Service?
Activity 通過 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 進行
繫結,當繫結成功的時候 Service 會將代理物件通過回撥的形式傳給 conn,這樣我們就拿到了
Service 提供的服務代理物件。
在 Activity 中可以通過 startService 和 bindService 方法啟動 Service。一般情況下如果想獲取
Service 的服務物件那麼肯定需要通過 bindService()方法,比如音樂播放器,第三方支付等。如
果僅僅只是為了開啟一個後臺任務那麼可以使用 startService()方法。
9.說說 Activity、Intent、Service 是什麼關係
他們都是 Android 開發中使用頻率最高的類。其中 Activity 和 Service 都是 Android 四大元件
之一。他倆都是 Context 類的子類 ContextWrapper 的子類,因此他倆可以算是兄弟關係吧。不過
兄弟倆各有各自的本領,Activity 負責使用者介面的顯示和互動,Service 負責後臺任務的處理。Activity
和 Service 之間可以通過 Intent 傳遞資料,因此可以把 Intent 看作是通訊使者。
10.請描述一下 BroadcastReceiver
BroadCastReceiver 是 Android 四大元件之一,主要用於接收系統或者 app 傳送的廣播事件。
廣播分兩種:有序廣播和無序廣播。
內部通訊實現機制:通過 Android 系統的 Binder 機制實現通訊。
1. 無序廣播:完全非同步,邏輯上可以被任何廣播接收者接收到。優點是效率較高。缺點是一個接收者不
能將處理結果傳遞給下一個接收者,並無法終止廣播 intent 的傳播。
2. 有序廣播:按照被接收者的優先順序順序,在被接收者中依次傳播。比如有三個廣播接收者 A,B,C,
優先順序是 A > B > C。那這個訊息先傳給 A,再傳給 B,最後傳給 C。每個接收者有權終止廣播,比
如 B 終止廣播,C 就無法接收到。此外 A 接收到廣播後可以對結果物件進行操作,當廣播傳給 B 時,
B 可以從結果物件中取得 A 存入的資料。
在通過 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
initialCode, initialData, initialExtras)時我們可以指定 resultReceiver 廣播接收者,這個接收者我們
可以認為是最終接收者,通常情況下如果比他優先順序更高的接收者如果沒有終止廣播,那麼他的
onReceive 會被執行兩次,第一次是正常的按照優先順序順序執行,第二次是作為最終接收者接收。
如果比他優先順序高的接收者終止了廣播,那麼他依然能接收到廣播
11.為什麼要用 ContentProvider?它和 sql 的實現上有什麼差別?
ContentProvider 遮蔽了資料儲存的細節,內部實現對使用者完全透明,使用者只需要關心操作資料的
uri 就可以了,ContentProvider 可以實現不同 app 之間共享。
Sql 也有增刪改查的方法,但是 sql 只能查詢本應用下的資料庫。而 ContentProvider 還可
以去增刪改查本地檔案. xml 檔案的讀取等。
12.說說 ContentProvider、ContentResolver、ContentObserver 之間的關係
a. ContentProvider 內容提供者,用於對外提供資料
b. ContentResolver.notifyChange(uri)發出訊息
c. ContentResolver 內容解析者,用於獲取內容提供者提供的資料
d. ContentObserver 內容監聽器,可以監聽資料的改變狀態
e. ContentResolver.registerContentObserver()監聽訊息。
View 相關
1.onInterceptTouchEvent()和onTouchEvent()的區別
onInterceptTouchEvent()用於攔截觸控事件
onTouchEvent()用於處理觸控事件
2.RemoteView在哪些功能中使用
APPwidget和Notification中
3. SurfaceView和View的區別是什麼?
SurfaceView中採用了雙快取技術,在單獨的執行緒中更新介面
View在UI執行緒中更新介面
4.View的繪製過程
一個View要顯示在介面上,需要經歷一個View樹的遍歷過程,這個過程又可以分為三個過程,也就是自定義View中的三要素:大小,位置,畫什麼,即onMesure(),onLayout(),onDraw()。
1.onMesure()確定一個View的大小;
2.onLayout()確定View在父節點上的位置;
3.onDraw()繪製View 的內容;
5.如何自定義ViewGroup
1.指定的LayoutParams
2.onMeasure中計算所有childView的寬和高,然後根據childView的寬和高,計算自己的寬和高。(當然,如果不是wrap_content,直接使用父ViewGroup傳入的計算值即可)
3.onLayout中對所有的childView進行佈局。
6.View中onTouch,onTouchEvent,onClick的執行順序
dispatchTouchEvent—->onTouch—->onTouchEvent—–>onClick。在所有ACTION_UP事件之後才觸發onClick點選事件。
效能優化相關
1.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。
2.如何避免 OOM 問題的出現
使用更加輕量的資料結構 例如,我們可以考慮使用ArrayMap/SparseArray而不是HashMap等傳統資料結構。通常的HashMap的實現方式更加消耗記憶體,因為它需要一個額外的例項物件來記錄Mapping操作。另外,SparseArray更加高效,在於他們避免了對key與value的自動裝箱(autoboxing),並且避免了裝箱後的解箱。
避免在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裡面使用到列舉。
減小Bitmap物件的記憶體佔用 Bitmap是一個極容易消耗記憶體的大胖子,減小創建出來的Bitmap的記憶體佔用可謂是重中之重,,通常來說有以下2個措施: ++inSampleSize++:縮放比例,在把圖片載入記憶體之前,我們需要先計算出一個合適的縮放比例,避免不必要的大圖載入。 ++decode format++:解碼格式,選擇ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差異
Bitmap物件的複用 縮小Bitmap的同時,也需要提高BitMap物件的複用率,避免頻繁建立BitMap物件,複用的方法有以下2個措施 LRUCache : “最近最少使用演算法”在Android中有極其普遍的應用。ListView與GridView等顯示大量圖片的控制元件裡,就是使用LRU的機制來快取處理好的Bitmap,把近期最少使用的資料從快取中移除,保留使用最頻繁的資料, inBitMap高階特性:利用inBitmap的高階特性提高Android系統在Bitmap分配與釋放執行效率。使用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經存在的記憶體區域,新解碼的Bitmap會嘗試去使用之前那張Bitmap在Heap中所佔據的pixel data記憶體區域,而不是去問記憶體重新申請一塊區域來存放Bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要佔用螢幕所能夠顯示的圖片數量的記憶體大小
使用更小的圖片 在涉及給到資源圖片時,我們需要特別留意這張圖片是否存在可以壓縮的空間,是否可以使用更小的圖片。儘量使用更小的圖片不僅可以減少記憶體的使用,還能避免出現大量的InflationException。假設有一張很大的圖片被XML檔案直接引用,很有可能在初始化檢視時會因為記憶體不足而發生InflationException,這個問題的根本原因其實是發生了OOM。
StringBuilder 在有些時候,程式碼中會需要使用到大量的字串拼接的操作,這種時候有必要考慮使用StringBuilder來替代頻繁的“+”。
避免在onDraw方法裡面執行物件的建立 類似onDraw等頻繁呼叫的方法,一定需要注意避免在這裡做建立物件的操作,因為他會迅速增加記憶體的使用,而且很容易引起頻繁的gc,甚至是記憶體抖動。
避免物件的記憶體洩露
3.三級快取的原理
從快取中載入。
從本地檔案中載入(資料庫,SD)
從網路載入。
a.載入 bitmap 的時候無需考慮 bitmap 載入過程中出現的 oom(記憶體溢位)和 android 容器快速
滑動的時候出現的圖片錯位等現象。(16M)
b. 支援載入網路圖片和本地圖片。
c. 記憶體管理使用的 lru 演算法(移除裡面是有頻率最少的物件),更好的管理 bitmap 的記憶體
Android其他
1.講一下android中程序的優先順序?
前臺程序
可見程序
服務程序
後臺程序
空程序
2.介紹Handle的機制
Handler通過呼叫sendmessage方法把訊息放在訊息佇列MessageQueue中,Looper負責把訊息從訊息佇列中取出來,重新再交給Handler進行處理,三者形成一個迴圈
通過構建一個訊息佇列,把所有的Message進行統一的管理,當Message不用了,並不作為垃圾回收,而是放入訊息佇列中,供下次handler建立訊息時候使用,提高了訊息物件的複用,減少系統垃圾回收的次數
每一個執行緒,都會單獨對應的一個looper,這個looper通過ThreadLocal來建立,保證每個執行緒只建立一個looper,looper初始化後就會呼叫looper.loop建立一個MessageQueue,這個方法在UI執行緒初始化的時候就會完成,我們不需要手動建立
3.Dalvik虛擬機器與JVM有什麼區別
Dalvik 基於暫存器,而 JVM 基於棧。基於暫存器的虛擬機器對於更大的程式來說,在它們編譯的時候,花費的時間更短。
Dalvik執行.dex格式的位元組碼,而JVM執行.class格式的位元組碼。
4.每個應用程式對應多少個Dalvik虛擬機器
每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機器例項,其程式碼在虛擬機器的解釋下得以執行 ,而所有的Android應用的執行緒都對應一個Linux執行緒
5.應用常駐後臺,避免被第三方殺掉的方法
Service設定成START_STICKY kill 後會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣
通過 startForeground將程序設定為前臺程序, 做前臺服務,優先順序和前臺應用一個級別,除非在系統記憶體非常缺,否則此程序不會被 kill
雙程序Service: 讓2個程序互相保護對方,其中一個Service被清理後,另外沒被清理的程序可以立即重啟程序
用C編寫守護程序(即子程序) : Android系統中當前程序(Process)fork出來的子程序,被系統認為是兩個不同的程序。當父程序被殺死的時候,子程序仍然可以存活,並不受影響(Android5.0以上的版本不可行
聯絡廠商,加入白名單
6.根據自己的理解描述下Android數字簽名。
所有的應用程式都必須有數字證書,Android系統不會安裝一個沒有數字證書的應用程式
Android程式包使用的數字證書可以是自簽名的,不需要一個權威的數字證書機構簽名認證
如果要正式釋出一個Android程式,必須使用一個合適的私鑰生成的數字證書來給程式簽名,而不能使用adt外掛或者ant工具生成的除錯證書來發布。
數字證書都是有有效期的,Android只是在應用程式安裝的時候才會檢查證書的有效期。如果程式已經安裝在系統中,即使證書過期也不會影響程式的正常功能。
7.Dalvik基於JVM的改進
幾個class變為一個dex,constant pool,省記憶體
Zygote,copy-on-write shared,省記憶體,省cpu,省電
基於暫存器的bytecode,省指令,省cpu,省電
Trace-based JIT,省cpu,省電,省記憶體
8.ARGB_8888佔用記憶體大小
本題的答案,是4byte,即ARGB各佔用8個位元來描述。
9.apk安裝解除安裝的原理
安裝過程:複製apk安裝包到data/app目錄下,解壓並掃描安裝包,把dex檔案(dalvik位元組碼)儲存到dalvik-cache目錄,並data/data目錄下建立對應的應用資料目錄。
解除安裝過程:刪除安裝過程中在上述三個目錄下建立的檔案及目錄。
10.通過Intent傳遞一些二進位制資料的方法有哪些?
使用Serializable介面實現序列化,這是Java常用的方法。
實現Parcelable介面,這裡Android的部分類比如Bitmap類就已經實現了,同時Parcelable在Android AIDL中交換資料也很常見的。
11.橫豎屏切換時Activity的生命週期
此時的生命週期跟清單檔案裡的配置有關係。
不設定Activity的android:configChanges時,切屏會重新呼叫各個生命週期預設首先銷燬當前activity,然後重新載入。
設定Activity android:configChanges=”orientation|keyboardHidden|screenSize”時,切屏不會重新呼叫各個生命週期,只會執行onConfigurationChanged方法
12.Serializable 和 Parcelable 的區別
在使用記憶體的時候,Parcelable 類比 Serializable 效能高,所以推薦使用 Parcelable 類。
1. Serializable 在序列化的時候會產生大量的臨時變數,從而引起頻繁的 GC。
2. Parcelable 不能使用在要將資料儲存在磁碟上的情況。儘管 Serializable 效率低點,但在這
種情況下,還是建議你用 Serializable 。
13.Android 中如何捕獲未捕獲的異常
自 定 義 一 個 Application , 比 如 叫 MyApplication 繼 承 Application 實 現
UncaughtExceptionHandler。
覆寫 UncaughtExceptionHandler 的 onCreate 和 uncaughtException 方法。
14.Android 的許可權規則
Android 中的 apk 必須簽名
基於 UserID 的程序級別的安全機制
預設 apk 生成的資料對外是不可見的
AndroidManifest.xml 中的顯式許可權宣告
15.多執行緒間通訊和多程序之間通訊有什麼不同,分別怎麼實現?
一、程序間的通訊方式
1. 管道( pipe ):管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的
程序間使用。程序的親緣關係通常是指父子程序關係。
2. 有名管道 (namedpipe) : 有名管道也是半雙工的通訊方式,但是它允許無親緣關係程序間的
通訊。
3. 訊號量(semophore ) : 訊號量是一個計數器,可以用來控制多個程序對共享資源的訪問。它
常作為一種鎖機制,防止某程序正在訪問共享資源時,其他程序也訪問該資源。因此,主要作為進
程間以及同一程序內不同執行緒之間的同步手段。
4. 訊息佇列( messagequeue ) : 訊息佇列是由訊息的連結串列,存放在核心中並由訊息佇列識別符號
標識。訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。
5. 訊號 (sinal ) : 訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生。
6. 共享記憶體(shared memory ) :共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享內
存由一個程序建立,但多個程序都可以訪問。共享記憶體是最快的 IPC 方式,它是針對其他程序間
通訊方式執行效率低而專門設計的。它往往與其他通訊機制,如訊號兩,配合使用,來實現程序間
的同步和通訊。
7. 套接字(socket ) : 套解口也是一種程序間通訊機制,與其他通訊機制不同的是,它可用於不同
及其間的程序通訊。
二、執行緒間的通訊方式
1. 鎖機制:包括互斥鎖、條件變數、讀寫鎖
*互斥鎖提供了以排他方式防止資料結構被併發修改的方法。
*讀寫鎖允許多個執行緒同時讀共享資料,而對寫操作是互斥的。
*條件變數可以以原子的方式阻塞程序,直到某個特定條件為真為止。對條件的測試是在互斥鎖
的保護下進行的。條件變數始終與互斥鎖一起使用。
2. 訊號量機制(Semaphore):包括無名執行緒訊號量和命名執行緒訊號量
3. 訊號機制(Signal):類似程序間的訊號處理
執行緒間的通訊目的主要是用於執行緒同步,所以執行緒沒有像程序通訊中的用於資料交換的通訊機
制。
16.說說 LruCache 底層原理
LruCache 使用一個 LinkedHashMap 簡單的實現記憶體的快取,沒有軟引用,都是強引用。如果添
加的資料大於設定的最大值,就刪除最先快取的資料來調整記憶體。
maxSize 是通過構造方法初始化的值,他表示這個快取能快取的最大值是多少。
size 在新增和移除快取都被更新值,他通過 safeSizeOf 這個方法更新值。safeSizeOf 預設返回 1,
但一般我們會根據 maxSize 重寫這個方法,比如認為 maxSize 代表是 KB 的話,那麼就以 KB 為單
位返回該項所佔的記憶體大小。
除異常外首先會判斷 size 是否超過 maxSize,如果超過了就取出最先插入的快取,如果不為空就
刪掉,並把 size 減去該項所佔的大小。這個操作將一直迴圈下去,直到 size 比 maxSize 小或者快取
為空。