- ThreadLocal實(shí)現(xiàn)原理
- EventBus原理
- EventBus流程
- EventBus內(nèi)ThreadMode類型分為4種
- HTTP 請求報(bào)文結(jié)構(gòu)
- HTTP 相應(yīng)報(bào)文結(jié)構(gòu)
- cookie是用來干嘛的
- android Intent 傳遞數(shù)據(jù)最大限制
- synchronize 關(guān)鍵字用法
- 還知道哪些同步的方式?
- Activity啟動(dòng)模式
- View的繪制流程首繁,測量傳參的形式是什么
- 內(nèi)部類有什么作用介却?
- final關(guān)鍵字的作用
- 單例模式為什么要兩次判空
- Android源碼中使用的設(shè)計(jì)模式
- APP啟動(dòng)優(yōu)化
- 分析內(nèi)存泄露的一些方法
ThreadLocal實(shí)現(xiàn)原理
每個(gè)Thread的對象都有一個(gè)ThreadLocalMap侮繁,當(dāng)創(chuàng)建一個(gè)ThreadLocal的時(shí)候首装,就會將該ThreadLocal對象添加到該Map中蓖乘,其中鍵就是ThreadLocal沿侈,值可以是任意類型霹娄。
在該類中,最重要的方法就是兩個(gè):set()和get()方法拣宏。當(dāng)調(diào)用ThreadLocal的get()方法的時(shí)候沈贝,會先找到當(dāng)前線程的ThreadLocalMap,然后再找到對應(yīng)的值勋乾。set()方法也是一樣宋下。)系統(tǒng)是如何監(jiān)聽ANR的(他說是androidframework層有一個(gè)單獨(dú)的進(jìn)程),后來問到如何定位和排查我不小心說了blockCanary辑莫,他有追問了一下源碼和原理我回答的也不是很好(應(yīng)用發(fā)生卡頓杨凑,一定是在dispatchMessage中執(zhí)行了耗時(shí)操作。我們通過給主線程的Looper設(shè)置一個(gè)Printer摆昧,打點(diǎn)統(tǒng)計(jì)dispatchMessage方法執(zhí)行的時(shí)間,如果超出閥值蜒程,表示發(fā)生卡頓绅你,則dump出各種信息伺帘,提供開發(fā)者分析性能瓶頸。
EventBus原理
EventBus是一個(gè)事件發(fā)布/訂閱總線忌锯。讓組件之間的通信更加簡單伪嫁。
- 針對在事件的發(fā)送者和訂閱者之間進(jìn)行解耦。
- 非常好的運(yùn)用在Activitys偶垮、Fragments和后臺線程张咳。
- 避開了聯(lián)系緊密易出錯(cuò)的依賴關(guān)系和容易出錯(cuò)生命周期。
EventBus 使用觀察者模式似舵,整體結(jié)構(gòu)基于發(fā)布者/訂閱者脚猾。訂閱者首先注冊,注冊以后,當(dāng)發(fā)布者發(fā)布數(shù)據(jù)的時(shí)候平臺就會吧這些數(shù)據(jù)發(fā)送給已經(jīng)注冊了的訂閱者(根據(jù)數(shù)據(jù)區(qū)分訂閱者)砚哗,訂閱者收到以后自行進(jìn)行處理龙助。
EventBus流程
- 注冊流程---register函數(shù)中會先根據(jù)訂閱者類名去subscriberMethodFinder中查找當(dāng)前訂閱者所有事件響應(yīng)函數(shù),然后循環(huán)每一個(gè)事件響應(yīng)函數(shù)蛛芥,依次執(zhí)行下面的 subscribe 函數(shù)提鸟。
第一,通過subscriptionsByEventType得到該事件類型的所有訂閱者信息隊(duì)列仅淑,根據(jù)優(yōu)先級把當(dāng)前訂閱者信息插入到訂閱者隊(duì)列subscriptionsByEventType中称勋。
第二,在typesBySubscriber中得到當(dāng)前訂閱者的所有事件隊(duì)列涯竟,將此事件保存到隊(duì)列typesBySubscriber中赡鲜,用于后續(xù)取消訂閱。
第三昆禽,檢查這個(gè)事件是否是 Sticky 事件蝗蛙,如果是則從stickyEvents事件保存隊(duì)列中取出該事件類型最后一個(gè)事件發(fā)送給當(dāng)前訂閱者。
- 發(fā)布流程---post方法會首先得到當(dāng)前線程的 post 信息PostingThreadState醉鳖,其中包含事件隊(duì)列捡硅,將當(dāng)前事件添加到其事件隊(duì)列中,然后循環(huán)調(diào)用 postSingleEvent 函數(shù)發(fā)布隊(duì)列中的每個(gè)事件盗棵。
postSingleEvent 方法會先去eventTypesCache得到該事件對應(yīng)類型的的父類及接口類型壮韭,沒有緩存則查找并插入緩存。循環(huán)得到的每個(gè)類型和接口纹因,調(diào)用 postSingleEventForEventType 方法發(fā)布每個(gè)事件到每個(gè)訂閱者喷屋。
postSingleEventForEventType 方法在subscriptionsByEventType查找該事件訂閱者訂閱者隊(duì)列,調(diào)用 postToSubscription 函數(shù)向每個(gè)訂閱者發(fā)布事件瞭恰。
EventBus內(nèi)ThreadMode類型分為4種
- PostThread屯曹,默認(rèn)的ThreadMore, 表示post操作的線程 直接調(diào)用給訂閱者的事件響應(yīng)接口,無論該線程是否為主線程。(如果post線程為主線程的時(shí)候恶耽,響應(yīng)接口不能有耗時(shí)操作密任,不然可能會卡主線程。)
- MainThread偷俭,在主線程執(zhí)行訂閱者的事件響應(yīng)接口浪讳。如果post就是主線程就直接調(diào)用,如果post不是主線程就通過Handler發(fā)送消息在主線程中處理涌萤。(響應(yīng)接口不能有耗時(shí)操作淹遵,不然可能會卡主線程。)
- BackgroundThread负溪,和MainThread正好相反透揣,在后臺線程中執(zhí)行訂閱者的事件響應(yīng)接口。如果post不在主線程就直接調(diào)用笙以,如果post在主線程就啟動(dòng)后臺線程去處理淌实。后臺線程是唯一的,所以當(dāng)事件超過一個(gè)時(shí)候猖腕,就放到隊(duì)列中依次執(zhí)行拆祈。(如果一個(gè)事件耗時(shí)太多,則會影響其他事件倘感,其他事件會排隊(duì)等待)
- Async放坏,不管post是不是主線程,都使用一個(gè)空閑線程執(zhí)行訂閱者的事件響應(yīng)接口老玛。(和BackgroundThread不一樣的是Async線程之間是獨(dú)立的淤年,一個(gè)事件有耗時(shí)也不會影響其他的事件執(zhí)行。)
HTTP 請求報(bào)文結(jié)構(gòu)
http請求報(bào)文由4部分組成:請求行蜡豹,請求頭部麸粮,空行,請求數(shù)據(jù)镜廉。
- 請求行,請求行主要目的是為了區(qū)分請求報(bào)文還是響應(yīng)報(bào)文弄诲,以及記錄相應(yīng)的URL以及協(xié)議版本。請求行分為三部分組成:方法娇唯、請求資源的URL齐遵、HTTP的版本。HTTP請求的方法主要有:GET塔插、POST梗摇、PUT、DELETE想许、OPTIONS伶授、HEAD断序、TRANCE、CONNECT等谎砾。
GET /URL HTTP/1.1
- 請求頭逢倍,是用來通知服務(wù)器有關(guān)客戶端請求的一些信息。請求頭是由key/value 鍵值對構(gòu)成景图,每行一對。(Accept碉哑、Host挚币、User-Agent等等都是請求頭中關(guān)鍵字)。
Host: www.baidu.com
User-Agent: curl/7.54.0
Accept: */*
....
- 空行扣典,請求頭的結(jié)尾妆毕。
- 請求數(shù)據(jù),GET方法沒有請求數(shù)據(jù)贮尖。為POST時(shí)放置的是需要提交的數(shù)據(jù)笛粘。
HTTP 相應(yīng)報(bào)文結(jié)構(gòu)
HTTP響應(yīng)報(bào)文也由三部分組成:響應(yīng)行、響應(yīng)頭湿硝、響應(yīng)體薪前。
- 響應(yīng)行,一般是由協(xié)議版本关斜,狀態(tài)碼極其表述組成示括。
HTTP/1.1 302 Found
- 響應(yīng)頭,用于描述服務(wù)器的基本信息和數(shù)據(jù)的描述信息痢畜,客戶端根據(jù)這些描述信息處理服務(wù)器回傳的數(shù)據(jù)垛膝。
< Date: Fri, 15 Mar 2019 10:03:18 GMT
< Server: Apache
< Location: http://www.baidu.com/search/error.html
< Cache-Control: max-age=86400
< Expires: Sat, 16 Mar 2019 10:03:18 GMT
< Content-Length: 222
< Connection: Keep-Alive
< Content-Type: text/html; charset=iso-8859-1
- 響應(yīng)體,服務(wù)器返回的數(shù)據(jù)丁稀。
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a >here</a>.</p>
</body></html>
cookie是用來干嘛的
一個(gè)由網(wǎng)頁服務(wù)器放在您硬盤上的非常小的文本文件.信息的片斷以‘名/值’對(name-value pairs)的形式儲存吼拥。 它本質(zhì)上就像您的身份證明一樣,可以方便網(wǎng)站“記住”用戶的偏好线衫,方便用戶使用網(wǎng)站的功能凿可,但是有些網(wǎng)站利用cookie精準(zhǔn)投放廣告。并且不能像代碼那樣被執(zhí)行或被用來散布病毒桶雀。它只能被您使用并且只能由提供的服務(wù)器讀取矿酵。
android Intent 傳遞數(shù)據(jù)最大限制
Intent傳遞數(shù)據(jù)最大為1兆
synchronize 關(guān)鍵字用法
synchronize是Java中的關(guān)鍵字,是一種同步鎖矗积。主要修飾以下幾種對象全肮。
- 修飾代碼塊,被修飾的代碼塊稱為同步語句塊棘捣,其作用的范圍是{}括起來的代碼辜腺,作用的對象是調(diào)用這個(gè)代碼塊的對象。
- 修飾一個(gè)方法,被修飾的方法稱為同步方法评疗,其作用范圍是整個(gè)方法测砂,作用的對象是調(diào)用這個(gè)方法的對象。
- 修飾一個(gè)靜態(tài)方法百匆,其作用的范圍是整個(gè)class對象砌些,對類的所有實(shí)例對象起作用。
- 修飾一個(gè)類加匈,其作用的范圍是synchronized后面括號括起來的部分存璃,作用主的對象是這個(gè)類的所有對象。
還知道哪些同步的方式雕拼?
LOCK
Activity啟動(dòng)模式
- Standard模式纵东,Standard是activity默認(rèn)的啟動(dòng)模式,使用此實(shí)例每次啟動(dòng)Activity,無論任務(wù)棧中是否已經(jīng)有這個(gè)Activity實(shí)例啥寇,系統(tǒng)都會新建一個(gè)Activity偎球。
- SingleTop模式,SingleTop和Standard差不多辑甜,區(qū)別是如果啟動(dòng)的Activity已經(jīng)在棧頂衰絮,則不會新建一個(gè)實(shí)例。如果不在棧頂?shù)臅r(shí)候才會新建一個(gè)實(shí)例栈戳。 如果Activity在棧頂?shù)臅r(shí)候重新啟動(dòng)的時(shí)候是不會調(diào)用onCreat()函數(shù)的岂傲,但是會調(diào)用onNewIntent()函數(shù)∽犹矗可以在onNewIntent()函數(shù)做相應(yīng)處理镊掖。
- SingleTask模式,在此模式下Activity在同一個(gè)Task任務(wù)棧內(nèi)只有一個(gè)實(shí)例褂痰。如果要啟動(dòng)的Activity在棧頂則和SingleTop模式一樣亩进,直接啟動(dòng)。如果不在棧頂缩歪,則把實(shí)例移到棧頂归薛,并把它上面的實(shí)例出棧。(如果指定了不同的taskAffinity則會啟動(dòng)一個(gè)新的任務(wù)棧)
- SingleInstance模式匪蝙,此模式也是單例主籍,但是和SingleTask不同,SingleTask是任務(wù)棧內(nèi)單例,SingleInstance是整個(gè)系統(tǒng)內(nèi)只有一個(gè)實(shí)例逛球,啟動(dòng)SingleInstance模式的Activity時(shí)千元,系統(tǒng)則會創(chuàng)建一個(gè)新的任務(wù)棧,并且這個(gè)任務(wù)棧只有這一個(gè)Activity颤绕。(舉例:A為普通默認(rèn)幸海,B為SingleInstance祟身,C為普通模式。A啟動(dòng)B物独,B啟動(dòng)C, C點(diǎn)擊返回袜硫,則會先銷毀C,然后銷毀A,最后銷毀B。因?yàn)锳和C是在同一個(gè)任務(wù)棧挡篓,所以銷毀C以后系統(tǒng)發(fā)現(xiàn)任務(wù)棧內(nèi)還有A所以也銷毀婉陷,然后才去銷毀B)。
View的繪制流程官研,測量傳參的形式是什么
整個(gè) View 樹的繪圖流程在ViewRoot.java類的performTraversals()函數(shù)展開憨攒,該函數(shù)所做 的工作可簡單概況為是否需要重新計(jì)算視圖大小(measure)、是否需要重新安置視圖的位置(layout)阀参、以及是否需要重繪(draw)。
用戶主動(dòng)調(diào)用 request瞻坝,只會出發(fā) measure 和 layout 過程蛛壳,而不會執(zhí)行 draw 過程。
View的繪制主要是三個(gè)方法所刀,onMouse()onLayout()衙荐、 onDraw();
onMouse()傳參會傳一個(gè)32位的int型數(shù)字浮创,高兩位代表測量模式(SpecMode)忧吟,低30位代表具體數(shù)值(SpecSize)。
SpecMode的取值可為以下三種:
- EXACTLY: 對子View提出了一個(gè)確切的建議尺寸(SpecSize)斩披;
- AT_MOST: 子View的大小不得超過SpecSize溜族;
- UNSPECIFIED:對子View的尺寸不作限制,通常用于系統(tǒng)內(nèi)部垦沉。
View 繪制流程函數(shù)調(diào)用鏈
圖片來源( https://plus.google.com/+ArpitMathur/posts/cT1EuBbxEgN)
內(nèi)部類有什么作用煌抒?
- 內(nèi)部類可以很好的實(shí)現(xiàn)隱藏,一般的非內(nèi)部類,是不允許有 private 與protected權(quán)限的厕倍,但內(nèi)部類可以寡壮。
- 內(nèi)部類擁有外圍類的所有元素的訪問權(quán)限 (private修飾也能訪問)
- 可是實(shí)現(xiàn)多重繼承 (讓多個(gè)內(nèi)部類分別繼承多個(gè)其他類,使外部類可以同時(shí)獲取多個(gè)其他類的屬性)
- 可以避免修改接口而實(shí)現(xiàn)同一個(gè)類中兩種同名方法的調(diào)用讹弯。(外部類繼承况既,讓內(nèi)部類實(shí)現(xiàn)接口)
final關(guān)鍵字的作用
- 被final修飾的類不可以被繼承
- 被final修飾的方法不可以被重寫
- 被final修飾的變量不可以被改變
- 被final修飾不可變的是變量的引用,而不是引用指向的內(nèi)容组民,引用指向的內(nèi)容是可以改變的棒仍。
單例模式為什么要兩次判空
雙重校驗(yàn)鎖模式
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
在極低的幾率下,通過if (instance == NULL)的線程才會有進(jìn)入鎖定臨界區(qū)的可能性邪乍,這種幾率還是比較低的降狠,不會阻塞太多的線程对竣,但為了防止一個(gè)線程進(jìn)入臨界區(qū)創(chuàng)建實(shí)例,另外的線程也進(jìn)去臨界區(qū)創(chuàng)建實(shí)例榜配,又加上了一道防御if (instance == NULL)否纬,這樣就確保不會重復(fù)創(chuàng)建了。
Android源碼中使用的設(shè)計(jì)模式
- 單例模式
- 建造者模式蛋褥,用于鏈?zhǔn)秸{(diào)用嫩海。
- 原型模式,
- 裝飾者模式-(動(dòng)態(tài)地給一個(gè)對象添加一些額外的職責(zé)凰浮。就增加功能來說选泻,裝飾者模式比生成子類更靈活)
APP啟動(dòng)優(yōu)化
- adb shell am start -W 首屏Activity。 啟動(dòng)時(shí)間統(tǒng)計(jì)
- 設(shè)置一個(gè)閃屏圖片背景的主題淫茵,讓用戶感覺點(diǎn)開以后就看到閃屏爪瓜,給用戶一種快的感覺,但是真實(shí)效率并沒有提升匙瘪。(這種治標(biāo)不治本铆铆,只是通過交互給用戶感覺的快)
- 通過業(yè)務(wù)邏輯優(yōu)化,比如延遲一些業(yè)務(wù)的初始化丹喻,通過一部線程處理一部分業(yè)務(wù)的初始化薄货。
- 盡量減少首屏activit密集的網(wǎng)絡(luò)請求“郏可以適當(dāng)緩存一些數(shù)據(jù)谅猾,下次打開應(yīng)用的時(shí)候使用。
分析內(nèi)存泄露的一些方法
- 把Java應(yīng)用程序使用的heap dump下來鳍悠,可以使用jdk里面帶的jmap工具税娜。
jmap -dump:format=b,file=heap.bin <pid>
format=b的含義是,dump出來的文件時(shí)二進(jìn)制格式贼涩。
file-heap.bin的含義是巧涧,dump出來的文件名是heap.bin。
<pid>就是JVM的進(jìn)程號遥倦。
(在linux下)先執(zhí)行ps aux | grep java谤绳,找到JVM的pid;然后再執(zhí)行jmap -dump:format=b,file=heap.bin <pid>袒哥,得到heap dump文件缩筛。
- 使用android 里面帶的DDMS內(nèi)的heap分析工具,找出內(nèi)存占用超出預(yù)期(一般是因?yàn)閿?shù)量太多)的嫌疑對象堡称。
- 內(nèi)存分析工具 MAT(Memory Analyzer Tool)瞎抛。