備戰(zhàn)Android面試

備戰(zhàn)Android面試(臨時(shí)發(fā)布,格式未調(diào)整完畢)

對(duì)于我面試時(shí)遇到的一些高頻問題尘盼,特此做一下記錄和一些本人收集的答案(可能會(huì)有錯(cuò),請(qǐng)大佬指正以便修改)

  1. Activity 啟動(dòng)模式/任務(wù)棧
    standard 模式
    這是默認(rèn)模式涛癌,每次激活A(yù)ctivity時(shí)都會(huì)創(chuàng)建Activity實(shí)例玉凯,并放入任務(wù)棧中。使用場(chǎng)景:大多數(shù)Activity她混。

singleTop 模式
如果在任務(wù)的棧頂正好存在該Activity的實(shí)例烈钞,就重用該實(shí)例( 會(huì)調(diào)用實(shí)例的 onNewIntent() ),否則就會(huì)創(chuàng)建新的實(shí)例并放入棧頂坤按,即使棧中已經(jīng)存在該Activity的實(shí)例毯欣,只要不在棧頂,都會(huì)創(chuàng)建新的實(shí)例臭脓。使用場(chǎng)景如新聞?lì)惢蛘唛喿x類App的內(nèi)容頁面酗钞。

singleTask 模式
如果在棧中已經(jīng)有該Activity的實(shí)例,就重用該實(shí)例(會(huì)調(diào)用實(shí)例的 onNewIntent() )来累。重用時(shí)砚作,會(huì)讓該實(shí)例回到棧頂,因此在它上面的實(shí)例將會(huì)被移出棧嘹锁。如果棧中不存在該實(shí)例葫录,將會(huì)創(chuàng)建新的實(shí)例放入棧中。使用場(chǎng)景如瀏覽器的主界面兼耀。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器压昼,只會(huì)啟動(dòng)主界面一次,其余情況都會(huì)走onNewIntent瘤运,并且會(huì)清空主界面上面的其他頁面窍霞。

singleInstance 模式
在一個(gè)新棧中創(chuàng)建該Activity的實(shí)例,并讓多個(gè)應(yīng)用共享該棧中的該Activity實(shí)例拯坟。一旦該模式的Activity實(shí)例已經(jīng)存在于某個(gè)棧中但金,任何應(yīng)用再激活該Activity時(shí)都會(huì)重用該棧中的實(shí)例( 會(huì)調(diào)用實(shí)例的 onNewIntent() )。其效果相當(dāng)于多個(gè)應(yīng)用共享一個(gè)應(yīng)用郁季,不管誰激活該 Activity 都會(huì)進(jìn)入同一個(gè)應(yīng)用中冷溃。使用場(chǎng)景如鬧鈴提醒,將鬧鈴提醒與鬧鈴設(shè)置分離梦裂。singleInstance不要用于中間頁面似枕,如果用于中間頁面,跳轉(zhuǎn)會(huì)有問題年柠,比如:A -> B (singleInstance) -> C凿歼,完全退出后,在此啟動(dòng),首先打開的是B答憔。

  1. 自定義View
    自定義控件:
    1味赃、組合控件。這種自定義控件不需要我們自己繪制虐拓,而是使用原生控件組合成的新控件心俗。如標(biāo)題欄。
    2蓉驹、繼承原有的控件城榛。這種自定義控件在原生控件提供的方法外,可以自己添加一些方法态兴。如制作圓角吠谢,圓形圖片。
    3诗茎、完全自定義控件:這個(gè)View上所展現(xiàn)的內(nèi)容全部都是我們自己繪制出來的。比如說制作水波紋進(jìn)度條献汗。

View的繪制流程:OnMeasure()——>OnLayout()——>OnDraw()

第一步:OnMeasure():測(cè)量視圖大小敢订。從頂層父View到子View遞歸調(diào)用measure方法,measure方法又回調(diào)OnMeasure罢吃。
第二步:OnLayout():確定View位置楚午,進(jìn)行頁面布局。從頂層父View向子View的遞歸調(diào)用view.layout方法的過程尿招,即父View根據(jù)上一步measure子View所得到的布局大小和布局參數(shù)矾柜,將子View放在合適的位置上。
第三步:OnDraw():繪制視圖就谜。ViewRoot創(chuàng)建一個(gè)Canvas對(duì)象怪蔑,然后調(diào)用OnDraw()。六個(gè)步驟:①丧荐、繪制視圖的背景缆瓣;②、保存畫布的圖層(Layer)虹统;③弓坞、繪制View的內(nèi)容;④车荔、繪制View子視圖渡冻,如果沒有就不用;
⑤忧便、還原圖層(Layer)族吻;⑥、繪制滾動(dòng)條。

3.View繪制流程

performTraversal()->performMeasure()->performLayout()->perfromDraw()->View/ViewGroup measure()->View/ViewGroup onMeasure()->View/ViewGroup layout()->View/ViewGroup onLayout()->View/ViewGroup draw()->View/ViewGroup onDraw()

  1. 怎樣加載超大圖

先下載到本地呼奢,BitmapRegionDecoder.decodeRegion()方法宜雀,通過傳入矩形區(qū)域即可顯示圖片的指定區(qū)域。

  1. Glide三級(jí)緩存

內(nèi)存緩存握础、硬盤緩存辐董、網(wǎng)絡(luò)緩存
內(nèi)存緩存是使用LruCache來進(jìn)行緩存的,強(qiáng)引用禀综,0.4*內(nèi)容容量是的最大內(nèi)存容量简烘。

  1. LRUCache算法是怎樣實(shí)現(xiàn)的

內(nèi)部存在一個(gè)LinkedHashMap和maxSize,把最近使用的對(duì)象用強(qiáng)引用存儲(chǔ)在 LinkedHashMap中定枷,給出來put和get方法孤澎,每次put圖片時(shí)計(jì)算緩存中所有圖片總大小,跟maxSize進(jìn)行比較欠窒,大于maxSize覆旭,就將最久添加的圖片移除;反之小于maxSize就添加進(jìn)來岖妄。
之前型将,我們會(huì)使用內(nèi)存緩存技術(shù)實(shí)現(xiàn),也就是軟引用或弱引用荐虐,在Android 2.3(APILevel 9)開始七兜,垃圾回收器會(huì)更傾向于回收持有軟引用或弱引用的對(duì)象,這讓軟引用和弱引用變得不再可靠福扬。

  1. 事件分發(fā)

dispatchTouchEvent()->onInterceptTouchEvent()->onTouchEvent()requestDisallowInterceptTouchEvent(boolean)

  1. Handler消息機(jī)制

創(chuàng)建 handler 的時(shí)候會(huì)創(chuàng)建一個(gè) looper(通過 looper.prepare() 來創(chuàng)建),looper 一般為主線程 looper.Handler 通過 send 發(fā)送消息(sendMessage) ,當(dāng)然 post 一系列方法最終也是通過 send 來實(shí)現(xiàn)的,在 send 方法中handler 會(huì)通過 enqueueMessage() 方法中的 enqueueMessage(msg,millis)向消息隊(duì)列 MessageQueue 插入一條消息,同時(shí)會(huì)把本身的 handler 通過 msg.target = this 傳入腕铸。Looper 是一個(gè)死循環(huán),不斷的讀取MessageQueue中的消息,loop 方法會(huì)調(diào)用 MessageQueue 的 next 方法來獲取新的消息,next操作是一個(gè)阻塞操作,當(dāng)沒有消息的時(shí)候 next 方法會(huì)一直阻塞,進(jìn)而導(dǎo)致 loop 一直阻塞,當(dāng)有消息的時(shí)候,Looper 就會(huì)處理消息 Looper 收到消息之后就開始處理消息: msg.target.dispatchMessage(msg),當(dāng)然這里的 msg.target 就是上面?zhèn)鬟^來的發(fā)送這條消息的 handler 對(duì)象,這樣 handler 發(fā)送的消息最終又交給他的dispatchMessage方法來處理了,這里不同的是,handler 的 dispatchMessage 方法是在創(chuàng)建 Handler時(shí)所使用的 Looper 中執(zhí)行的,這樣就成功的將代碼邏輯切換到了主線程了.

Handler 處理消息的過程是:首先,檢查Message 的 callback 是否為 null,不為 null 就通過 handleCallBack 來處理消息,Message 的 callback 是一個(gè) Runnable 對(duì)象,實(shí)際上是 handler 的 post 方法所傳遞的 Runnable 參數(shù).其次是檢查 mCallback 是 否為 null,不為 null 就調(diào)用 mCallback 的handleMessage 方法來處理消息.

  1. 為什么主線程不會(huì)因?yàn)長(zhǎng)ooper.loop()里的死循環(huán)卡死
    在代碼ActivityThread.main()中
public static void main(String[] args) {
        ....

        //創(chuàng)建Looper和MessageQueue對(duì)象,用于處理主線程的消息
        Looper.prepareMainLooper();

        //創(chuàng)建ActivityThread對(duì)象
        ActivityThread thread = new ActivityThread(); 

        //建立Binder通道 (創(chuàng)建新線程)
        thread.attach(false);

        Looper.loop(); //消息循環(huán)運(yùn)行
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

thread.attach(false)铛碑;便會(huì)創(chuàng)建一個(gè)Binder線程(具體是指ApplicationThread狠裹,Binder的服務(wù)端,用于接收系統(tǒng)服務(wù)AMS發(fā)送來的事件)亚茬,該Binder線程通過Handler將Message發(fā)送給主線程

8.HandlerThread

總的來說酪耳,Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback()); 這樣子傳參可以使得childHandler的handlerMessage可以處理異步任務(wù)。具體看:https://blog.csdn.net/javazejian/article/details/52426353

9.IntentService

它本質(zhì)是一種特殊的Service,繼承自Service并且本身就是一個(gè)抽象類
它可以用于在后臺(tái)執(zhí)行耗時(shí)的異步任務(wù)刹缝,當(dāng)任務(wù)完成后會(huì)自動(dòng)停止
它擁有較高的優(yōu)先級(jí)碗暗,不易被系統(tǒng)殺死(繼承自Service的緣故),因此比較適合執(zhí)行一些高優(yōu)先級(jí)的異步任務(wù)
它內(nèi)部通過HandlerThread和Handler實(shí)現(xiàn)異步操作
創(chuàng)建IntentService時(shí)梢夯,只需實(shí)現(xiàn)onHandleIntent和構(gòu)造方法言疗,onHandleIntent為異步方法,可以執(zhí)行耗時(shí)操作
只可以startService方式啟動(dòng)

10.HashMap底層實(shí)現(xiàn)

JDK 1.8對(duì)HashMap進(jìn)行了比較大的優(yōu)化颂砸,底層實(shí)現(xiàn)由之前的“數(shù)組+鏈表”改為“數(shù)組+鏈表+紅黑樹”噪奄,當(dāng)鏈表節(jié)點(diǎn)較少時(shí)仍然是以鏈表存在死姚,當(dāng)鏈表節(jié)點(diǎn)較多時(shí)(大于8)會(huì)轉(zhuǎn)為紅黑樹。數(shù)組默認(rèn)容量16勤篮,hashCode()再計(jì)算hash的值為數(shù)組都毒,HashMap的擴(kuò)容為原來的2倍,HashMap允許key和value為null碰缔。
紅黑樹平衡的幾條性質(zhì):
1.節(jié)點(diǎn)是紅色或黑色账劲。
2.根是黑色。
3.所有葉子都是黑色(葉子是NIL節(jié)點(diǎn))金抡。
4.每個(gè)紅色節(jié)點(diǎn)必須有兩個(gè)黑色的子節(jié)點(diǎn)瀑焦。(從每個(gè)葉子到根的所有路徑上不能有兩個(gè)連續(xù)的紅色節(jié)點(diǎn)。)
5.從任一節(jié)點(diǎn)到其每個(gè)葉子的所有簡(jiǎn)單路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)梗肝。

11.ArrayList 和 LinkedList 區(qū)別

ArrayList是基于初始大小為10動(dòng)態(tài)數(shù)組榛瓮,新的容量=“(原始容量x3)/2+1”,擴(kuò)容是1.5倍增加數(shù)組巫击,再將原數(shù)組copy到已經(jīng)擴(kuò)容的數(shù)組禀晓,LinkedList本質(zhì)是雙向鏈表,包含兩個(gè)重要的成員:header 和 size坝锰。header是雙向鏈表的表頭匆绣,它是雙向鏈表節(jié)點(diǎn)所對(duì)應(yīng)的類Entry的實(shí)例。Entry中包含成員變量:previous,next,element什黑。其中,previous是該節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)堪夭,next是該節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)愕把,element是該節(jié)點(diǎn)所包含的值。size是雙向鏈表中節(jié)點(diǎn)的個(gè)數(shù)森爽。適用場(chǎng)景:當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行對(duì)此訪問的情況下選用ArrayList恨豁,當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行多次增加刪除修改時(shí)采用LinkedList。

12.內(nèi)存泄露

產(chǎn)生的內(nèi)存泄露
1).資源對(duì)象沒關(guān)閉造成的內(nèi)存泄漏
2).構(gòu)造Adapter時(shí)爬迟,沒有使用緩存的convertView
3).Bitmap對(duì)象不在使用時(shí)調(diào)用recycle()釋放內(nèi)存
4).試著使用關(guān)于application的context來替代和activity相關(guān)的context
5).注冊(cè)沒取消造成的內(nèi)存泄漏
6).集合中對(duì)象沒清理造成的內(nèi)存泄漏

7).Handler 造成的內(nèi)存泄漏,我們知道消息隊(duì)列是在一個(gè) Looper 線程中不斷輪詢處理消息橘蜜,那么當(dāng)這個(gè) Activity 退出時(shí)消息隊(duì)列中還有未處理的消息或者正在處理消息,而消息隊(duì)列中的 Message 持有 mHandler 實(shí)例的引用付呕,mHandler 又持有 Activity的引用计福,所以導(dǎo)致該 Activity 的內(nèi)存資源無法及時(shí)回收,引發(fā)內(nèi)存泄漏

查找內(nèi)存泄漏
查找內(nèi)存泄漏可以使用Android Studio 自帶的Android Profiler工具,也可以使用Square產(chǎn)品的LeadCanary.
優(yōu)化方案:https://mp.weixin.qq.com/s/SmW2ljasKSXC1zlwTLY-iQ

13.Android優(yōu)化
性能優(yōu)化
1).節(jié)制的使用Service 如果應(yīng)用程序需要使用Service來執(zhí)行后臺(tái)任務(wù)的話徽职,只有當(dāng)任務(wù)正在執(zhí)行的時(shí)候才應(yīng)該讓Service運(yùn)行起來象颖。當(dāng)啟動(dòng)一個(gè)Service時(shí),系統(tǒng)會(huì)傾向于將這個(gè)Service所依賴的進(jìn)程進(jìn)行保留姆钉,系統(tǒng)可以在LRUcache當(dāng)中緩存的進(jìn)程數(shù)量也會(huì)減少说订,導(dǎo)致切換程序的時(shí)候耗費(fèi)更多性能抄瓦。我們可以使用IntentService,當(dāng)后臺(tái)任務(wù)執(zhí)行結(jié)束后會(huì)自動(dòng)停止陶冷,避免了Service的內(nèi)存泄漏钙姊。
2).當(dāng)界面不可見時(shí)釋放內(nèi)存 當(dāng)用戶打開了另外一個(gè)程序,我們的程序界面已經(jīng)不可見的時(shí)候埂伦,我們應(yīng)當(dāng)將所有和界面相關(guān)的資源進(jìn)行釋放煞额。重寫Activity的onTrimMemory()方法,然后在這個(gè)方法中監(jiān)聽TRIM_MEMORY_UI_HIDDEN這個(gè)級(jí)別赤屋,一旦觸發(fā)說明用戶離開了程序立镶,此時(shí)就可以進(jìn)行資源釋放操作了。
3).當(dāng)內(nèi)存緊張時(shí)釋放內(nèi)存 onTrimMemory()方法還有很多種其他類型的回調(diào)类早,可以在手機(jī)內(nèi)存降低的時(shí)候及時(shí)通知我們媚媒,我們應(yīng)該根據(jù)回調(diào)中傳入的級(jí)別來去決定如何釋放應(yīng)用程序的資源。
4).避免在Bitmap上浪費(fèi)內(nèi)存 讀取一個(gè)Bitmap圖片的時(shí)候涩僻,千萬不要去加載不需要的分辨率缭召。可以壓縮圖片等操作逆日。
5).使用優(yōu)化過的數(shù)據(jù)集合 Android提供了一系列優(yōu)化過后的數(shù)據(jù)集合工具類嵌巷,如SparseArray、SparseBooleanArray室抽、LongSparseArray搪哪,使用這些API可以讓我們的程序更加高效。HashMap工具類會(huì)相對(duì)比較低效坪圾,因?yàn)樗枰獮槊恳粋€(gè)鍵值對(duì)都提供一個(gè)對(duì)象入口晓折,而SparseArray就避免掉了基本數(shù)據(jù)類型轉(zhuǎn)換成對(duì)象數(shù)據(jù)類型的時(shí)間。

布局優(yōu)化
1).重用布局文件
標(biāo)簽可以允許在一個(gè)布局當(dāng)中引入另一個(gè)布局兽泄,那么比如說我們程序的所有界面都有一個(gè)公共的部分漓概,這個(gè)時(shí)候最好的做法就是將這個(gè)公共的部分提取到一個(gè)獨(dú)立的布局中,然后每個(gè)界面的布局文件當(dāng)中來引用這個(gè)公共的布局病梢。
Tips:如果我們要在標(biāo)簽中覆寫layout屬性胃珍,必須要將layout_width和layout_height這兩個(gè)屬性也進(jìn)行覆寫,否則覆寫效果將不會(huì)生效蜓陌。
標(biāo)簽是作為標(biāo)簽的一種輔助擴(kuò)展來使用的觅彰,它的主要作用是為了防止在引用布局文件時(shí)引用文件時(shí)產(chǎn)生多余的布局嵌套。布局嵌套越多钮热,解析起來就越耗時(shí)缔莲,性能就越差。因此編寫布局文件時(shí)應(yīng)該讓嵌套的層數(shù)越少越好霉旗。
舉例:比如在LinearLayout里邊使用一個(gè)布局痴奏。里邊又有一個(gè)LinearLayout蛀骇,那么其實(shí)就存在了多余的布局嵌套,使用merge可以解決這個(gè)問題读拆。

2).僅在需要時(shí)才加載布局
某個(gè)布局當(dāng)中的元素不是一起顯示出來的擅憔,普通情況下只顯示部分常用的元素,而那些不常用的元素只有在用戶進(jìn)行特定操作時(shí)才會(huì)顯示出來檐晕。
舉例:填信息時(shí)不是需要全部填的暑诸,有一個(gè)添加更多字段的選項(xiàng),當(dāng)用戶需要添加其他信息的時(shí)候辟灰,才將另外的元素顯示到界面上个榕。用VISIBLE性能表現(xiàn)一般,可以用ViewStub芥喇。ViewStub也是View的一種西采,但是沒有大小,沒有繪制功能继控,也不參與布局械馆,資源消耗非常低,可以認(rèn)為完全不影響性能武通。

tips:ViewStub所加載的布局是不可以使用標(biāo)簽的霹崎,因此這有可能導(dǎo)致加載出來出來的布局存在著多余的嵌套結(jié)構(gòu)。

高性能編碼優(yōu)化
都是一些微優(yōu)化冶忱,在性能方面看不出有什么顯著的提升的尾菇。使用合適的算法和數(shù)據(jù)結(jié)構(gòu)是優(yōu)化程序性能的最主要手段。

1).避免創(chuàng)建不必要的對(duì)象 不必要的對(duì)象我們應(yīng)該避免創(chuàng)建:
如果有需要拼接的字符串囚枪,那么可以優(yōu)先考慮使用StringBuffer或者StringBuilder來進(jìn)行拼接错沽,而不是加號(hào)連接符,因?yàn)槭褂眉犹?hào)連接符會(huì)創(chuàng)建多余的對(duì)象眶拉,拼接的字符串越長(zhǎng),加號(hào)連接符的性能越低憔儿。
當(dāng)一個(gè)方法的返回值是String的時(shí)候忆植,通常需要去判斷一下這個(gè)String的作用是什么,如果明確知道調(diào)用方會(huì)將返回的String再進(jìn)行拼接操作的話谒臼,可以考慮返回一個(gè)StringBuffer對(duì)象來代替朝刊,因?yàn)檫@樣可以將一個(gè)對(duì)象的引用進(jìn)行返回,而返回String的話就是創(chuàng)建了一個(gè)短生命周期的臨時(shí)對(duì)象蜈缤。
盡可能地少創(chuàng)建臨時(shí)對(duì)象拾氓,越少的對(duì)象意味著越少的GC操作。
2).在沒有特殊原因的情況下底哥,盡量使用基本數(shù)據(jù)類型來代替封裝數(shù)據(jù)類型咙鞍,int比Integer要更加有效房官,其它數(shù)據(jù)類型也是一樣。
基本數(shù)據(jù)類型的數(shù)組也要優(yōu)于對(duì)象數(shù)據(jù)類型的數(shù)組续滋。另外兩個(gè)平行的數(shù)組要比一個(gè)封裝好的對(duì)象數(shù)組更加高效翰守,舉個(gè)例子,F(xiàn)oo[]和Bar[]這樣的數(shù)組疲酌,使用起來要比Custom(Foo,Bar)[]這樣的一個(gè)數(shù)組高效的多蜡峰。
3).靜態(tài)優(yōu)于抽象
如果你并不需要訪問一個(gè)對(duì)系那個(gè)中的某些字段,只是想調(diào)用它的某些方法來去完成一項(xiàng)通用的功能朗恳,那么可以將這個(gè)方法設(shè)置成靜態(tài)方法湿颅,調(diào)用速度提升15%-20%,同時(shí)也不用為了調(diào)用這個(gè)方法去專門創(chuàng)建對(duì)象了粥诫,也不用擔(dān)心調(diào)用這個(gè)方法后是否會(huì)改變對(duì)象的狀態(tài)(靜態(tài)方法無法訪問非靜態(tài)字段)油航。
4).對(duì)常量使用static final修飾符

static int intVal = 42;  
static String strVal = "Hello, world!"; 

編譯器會(huì)為上面的代碼生成一個(gè)初始方法,稱為方法臀脏,該方法會(huì)在定義類第一次被使用的時(shí)候調(diào)用劝堪。這個(gè)方法會(huì)將42的值賦值到intVal當(dāng)中,從字符串常量表中提取一個(gè)引用賦值到strVal上揉稚。當(dāng)賦值完成后秒啦,我們就可以通過字段搜尋的方式去訪問具體的值了。
final進(jìn)行優(yōu)化:

static final int intVal = 42;
static final String strVal = "Hello, world!";
這樣搀玖,定義類就不需要方法了余境,因?yàn)樗械某A慷紩?huì)在dex文件的初始化器當(dāng)中進(jìn)行初始化。當(dāng)我們調(diào)用intVal時(shí)可以直接指向42的值灌诅,而調(diào)用strVal會(huì)用一種相對(duì)輕量級(jí)的字符串常量方式芳来,而不是字段搜尋的方式。
這種優(yōu)化方式只對(duì)基本數(shù)據(jù)類型以及String類型的常量有效猜拾,對(duì)于其他數(shù)據(jù)類型的常量是無效的即舌。
5).使用增強(qiáng)型for循環(huán)語法

static class Counter {  
int mCount;  
}  

Counter[] mArray = ...  

public void zero() {  
int sum = 0;  
for (int i = 0; i < mArray.length; ++i) {  
    sum += mArray[i].mCount;  
}  }  

public void one() {  
int sum = 0;  
Counter[] localArray = mArray;  
int len = localArray.length;  
for (int i = 0; i < len; ++i) {  
    sum += localArray[i].mCount;  
}  
}  

public void two() {  
int sum = 0;  
for (Counter a : mArray) {  
    sum += a.mCount;  
}  
}  

zero()最慢,每次都要計(jì)算mArray的長(zhǎng)度挎袜,one()相對(duì)快得多顽聂,two()fangfa在沒有JIT(Just In Time Compiler)的設(shè)備上是運(yùn)行最快的,而在有JIT的設(shè)備上運(yùn)行效率和one()方法不相上下盯仪,需要注意這種寫法需要JDK1.5之后才支持紊搪。
Tips:ArrayList手寫的循環(huán)比增強(qiáng)型for循環(huán)更快,其他的集合沒有這種情況全景。因此默認(rèn)情況下使用增強(qiáng)型for循環(huán)耀石,而遍歷ArrayList使用傳統(tǒng)的循環(huán)方式。
6).多使用系統(tǒng)封裝好的API
系統(tǒng)提供不了的Api完成不了我們需要的功能才應(yīng)該自己去寫爸黄,因?yàn)槭褂孟到y(tǒng)的Api很多時(shí)候比我們自己寫的代碼要快得多滞伟,它們的很多功能都是通過底層的匯編模式執(zhí)行的揭鳞。 舉個(gè)例子,實(shí)現(xiàn)數(shù)組拷貝的功能诗良,使用循環(huán)的方式來對(duì)數(shù)組中的每一個(gè)元素一一進(jìn)行賦值當(dāng)然可行汹桦,但是直接使用系統(tǒng)中提供的System.arraycopy()方法會(huì)讓執(zhí)行效率快9倍以上。
7).避免在內(nèi)部調(diào)用Getters/Setters方法
面向?qū)ο笾蟹庋b的思想是不要把類內(nèi)部的字段暴露給外部鉴裹,而是提供特定的方法來允許外部操作相應(yīng)類的內(nèi)部字段舞骆。但在Android中,字段搜尋比方法調(diào)用效率高得多径荔,我們直接訪問某個(gè)字段可能要比通過getters方法來去訪問這個(gè)字段快3到7倍督禽。但是編寫代碼還是要按照面向?qū)ο笏季S的,我們應(yīng)該在能優(yōu)化的地方進(jìn)行優(yōu)化总处,比如避免在內(nèi)部調(diào)用getters/setters方法狈惫。

14.屏幕適配
1.“布局”匹配,使用限定符
尺寸(size)限定符
最小寬度(Smallest-width)限定符
布局別名
屏幕方向(Orientation)限定符
2.“布局組件”匹配鹦马,使得布局組件自適應(yīng)屏幕尺寸
3.“圖片資源”匹配
使用自動(dòng)拉伸位圖:Nine-Patch的圖片類型

15.Context胧谈、Activity、Service荸频、Application
Context是一個(gè)抽象基類菱肖。在翻譯為上下文,也可以理解為環(huán)境旭从,是提供一些程序的運(yùn)行環(huán)境基礎(chǔ)信息稳强。Context下有兩個(gè)子類,ContextWrapper是上下文功能的封裝類和悦,而ContextImpl則是上下文功能的實(shí)現(xiàn)類退疫。而ContextWrapper又有三個(gè)直接的子類, ContextThemeWrapper鸽素、Service和Application褒繁。其中,ContextThemeWrapper是一個(gè)帶主題的封裝類馍忽,而它有一個(gè)直接子類就是Activity棒坏,所以Activity和Service以及Application的Context是不一樣的,只有Activity需要主題舵匾,Service不需要主題。

Context一共有三種類型谁不,分別是Application坐梯、Activity和Service。這三個(gè)類雖然分別各種承擔(dān)著不同的作用刹帕,但它們都屬于Context的一種吵血,而它們具體Context的功能則是由ContextImpl類去實(shí)現(xiàn)的谎替,因此在絕大多數(shù)場(chǎng)景下,Activity蹋辅、Service和Application這三種類型的Context都是可以通用的钱贯。不過有幾種場(chǎng)景比較特殊,比如啟動(dòng)Activity侦另,還有彈出Dialog秩命。出于安全原因的考慮,Android是不允許Activity或Dialog憑空出現(xiàn)的褒傅,一個(gè)Activity的啟動(dòng)必須要建立在另一個(gè)Activity的基礎(chǔ)之上弃锐,也就是以此形成的返回棧。而Dialog則必須在一個(gè)Activity上面彈出(除非是System Alert類型的Dialog)殿托,因此在這種場(chǎng)景下霹菊,我們只能使用Activity類型的Context,否則將會(huì)出錯(cuò)支竹。

getApplicationContext()和getApplication()方法得到的對(duì)象都是同一個(gè)application對(duì)象旋廷,只是對(duì)象的類型不一樣。
Context數(shù)量 = Activity數(shù)量 + Service數(shù)量 + 1 (1為Application)

16.AIDL
AIDL: 每一個(gè)進(jìn)程都有自己的Dalvik VM實(shí)例礼搁,都有自己的一塊獨(dú)立的內(nèi)存饶碘,都在自己的內(nèi)存上存儲(chǔ)自己的數(shù)據(jù),執(zhí)行著自己的操作叹坦,都在自己的那片狹小的空間里過完自己的一生熊镣。而aidl就類似與兩個(gè)進(jìn)程之間的橋梁,使得兩個(gè)進(jìn)程之間可以進(jìn)行數(shù)據(jù)的傳輸募书,跨進(jìn)程通信有多種選擇绪囱,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系統(tǒng)資源比較多莹捡,如果是頻繁的跨進(jìn)程通信的話顯然是不可取的鬼吵;Messenger 進(jìn)行跨進(jìn)程通信時(shí)請(qǐng)求隊(duì)列是同步進(jìn)行的,無法并發(fā)執(zhí)行篮赢。

Binde機(jī)制簡(jiǎn)單理解:
在Android系統(tǒng)的Binder機(jī)制中齿椅,是有Client,Service,ServiceManager,Binder驅(qū)動(dòng)程序組成的,其中Client启泣,service涣脚,Service Manager運(yùn)行在用戶空間,Binder驅(qū)動(dòng)程序是運(yùn)行在內(nèi)核空間的寥茫。而Binder就是把這4種組件粘合在一塊的粘合劑遣蚀,其中核心的組件就是Binder驅(qū)動(dòng)程序,Service Manager提供輔助管理的功能,而Client和Service正是在Binder驅(qū)動(dòng)程序和Service Manager提供的基礎(chǔ)設(shè)施上實(shí)現(xiàn)C/S 之間的通信芭梯。其中Binder驅(qū)動(dòng)程序提供設(shè)備文件/dev/binder與用戶控件進(jìn)行交互险耀,
Client、Service玖喘,Service Manager通過open和ioctl文件操作相應(yīng)的方法與Binder驅(qū)動(dòng)程序進(jìn)行通信甩牺。而Client和Service之間的進(jìn)程間通信是通過Binder驅(qū)動(dòng)程序間接實(shí)現(xiàn)的。而Binder Manager是一個(gè)守護(hù)進(jìn)程累奈,用來管理Service贬派,并向Client提供查詢Service接口的能力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末费尽,一起剝皮案震驚了整個(gè)濱河市赠群,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旱幼,老刑警劉巖查描,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異柏卤,居然都是意外死亡冬三,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門缘缚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勾笆,“玉大人,你說我怎么就攤上這事桥滨∥炎Γ” “怎么了?”我有些...
    開封第一講書人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵齐媒,是天一觀的道長(zhǎng)蒲每。 經(jīng)常有香客問我,道長(zhǎng)喻括,這世上最難降的妖魔是什么邀杏? 我笑而不...
    開封第一講書人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮唬血,結(jié)果婚禮上望蜡,老公的妹妹穿的比我還像新娘。我一直安慰自己拷恨,他們只是感情好脖律,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腕侄,像睡著了一般小泉。 火紅的嫁衣襯著肌膚如雪勒叠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,798評(píng)論 1 290
  • 那天膏孟,我揣著相機(jī)與錄音,去河邊找鬼拌汇。 笑死柒桑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的噪舀。 我是一名探鬼主播魁淳,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼与倡!你這毒婦竟也來了界逛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤纺座,失蹤者是張志新(化名)和其女友劉穎息拜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體净响,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡少欺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了馋贤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赞别。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖配乓,靈堂內(nèi)的尸體忽然破棺而出仿滔,到底是詐尸還是另有隱情,我是刑警寧澤犹芹,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布崎页,位于F島的核電站,受9級(jí)特大地震影響羽莺,放射性物質(zhì)發(fā)生泄漏实昨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一盐固、第九天 我趴在偏房一處隱蔽的房頂上張望荒给。 院中可真熱鬧,春花似錦刁卜、人聲如沸志电。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挑辆。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鱼蝉,已是汗流浹背洒嗤。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魁亦,地道東北人渔隶。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像洁奈,于是被迫代替她去往敵國(guó)和親间唉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容