2020年Android面試題大全(附答案)

面試題包含java基礎(chǔ)忽你,數(shù)據(jù)結(jié)構(gòu)幼东,網(wǎng)絡(luò),Android科雳,設(shè)計(jì)模式根蟹,Jvm,Kotlin等糟秘。適合中高級工程師简逮。

一:Java基礎(chǔ)


1.Object

equals和==的區(qū)別?equals和hashcode的關(guān)系蚌堵?

==:基本類型比較值买决,引用類型比較地址。

equals:默認(rèn)情況下吼畏,equals作為對象中的方法督赤,比較的是地址,不過可以根據(jù)業(yè)務(wù)泻蚊,修改equals方法躲舌,比如String就重寫了equals方法。

默認(rèn)情況下性雄,equals相等没卸,hashcode必相等,hashcode相等秒旋,equals不是必相等约计、hashcode基于內(nèi)存地址計(jì)算得出,可能會相等迁筛,雖然幾率微乎其微煤蚌。

2.String

String,StringBuffer和StringBuilder的區(qū)別?

String:String屬于不可變對象细卧,每次修改都會生成新的對象尉桩。

StringBuilder:可變對象,非多線程安全贪庙,效率高于StringBuffer

StringBuffer:可變對象蜘犁,多線程安全。

效率:StringBuilder>StringBuffer>String

3.面向?qū)ο蟮奶卣?/h4>

java中抽象類和接口的特點(diǎn)止邮?

共同點(diǎn):

1.抽象類和接口都不能生成具體的實(shí)例这橙。

2.都是作為上層使用奏窑。

不同點(diǎn):

1.抽象類可以有屬性和成員方法,接口不可以析恋。

2.一個(gè)類只能繼承一個(gè)類良哲,但是可以實(shí)現(xiàn)多個(gè)接口。

3.抽象類中的變量是普通變量助隧,接口中的變量是靜態(tài)變量筑凫。

4.抽象類表達(dá)的是一種is-a的關(guān)系,即父類和派生子類在概念上的本質(zhì)是相同的并村。

5.接口表達(dá)的是一種like-a的關(guān)系巍实,即接口和實(shí)現(xiàn)類的關(guān)系只是實(shí)現(xiàn)了定義行為,并無本質(zhì)上的聯(lián)系哩牍。

關(guān)于多態(tài)的理解棚潦?

多態(tài)是面向?qū)ο蟮娜筇匦裕豪^承,封裝和多態(tài)之一膝昆。

多態(tài)的定義:允許不同類對同一消息做出響應(yīng)丸边。

多態(tài)存在的條件

1.要有繼承。

2.要有復(fù)寫荚孵。

3.父類引用指向子類對象妹窖。

java中多態(tài)的實(shí)現(xiàn)方式:接口實(shí)現(xiàn),繼承父類進(jìn)行方法重寫收叶,同一個(gè)類中的方法重載骄呼。

4.集合

HashMap的特點(diǎn)是什么?HashMap的原理判没?

HashMap的特點(diǎn):

1.通過鍵的Hash值確定數(shù)組的位置蜓萄。

2.找到以后,如果該位置無節(jié)點(diǎn)澄峰,直接存放嫉沽。

3.該位置有節(jié)點(diǎn)即位置發(fā)生沖突,遍歷該節(jié)點(diǎn)以及后續(xù)的節(jié)點(diǎn)俏竞,比較key值耻蛇,相等則覆蓋。

4.沒有就新增節(jié)點(diǎn)胞此,默認(rèn)使用鏈表,相連節(jié)點(diǎn)數(shù)超過8的時(shí)候跃捣,在jdk1.8中會變成紅黑樹漱牵。

5.如果Hashmap中的數(shù)組使用情況超過一定比例,就回?cái)U(kuò)容疚漆,默認(rèn)擴(kuò)容兩倍酣胀。

這是存入的過程刁赦。需要注意的是:

key的hash值計(jì)算過程是高16位不變,低16位取抑或闻镶,讓更多位參與進(jìn)來甚脉,可以有效的減少碰撞的發(fā)生。

初始數(shù)組容量為16铆农,默認(rèn)不超過的比例為0.75.

5.泛型

泛型的本質(zhì)是參數(shù)化類型牺氨,在不創(chuàng)建新的類型的情況下,通過泛型指定不同的類型來控制形參具體限制的類型墩剖。也就是說在泛型的使用中猴凹,操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù),這種參數(shù)可以被用在類岭皂,接口和方法中郊霎,分別被稱為泛型類,泛型接口和泛型方法爷绘。

泛型是java中的一種語法糖书劝,能夠在代碼編寫的時(shí)候起到類型檢測的作用,但是虛擬機(jī)是不支持這些語法的土至。

泛型的優(yōu)點(diǎn):

1.類型安全购对,避免類型的強(qiáng)轉(zhuǎn)。

2.提高了代碼的可讀性毙籽,不必要等到運(yùn)行的時(shí)候才去強(qiáng)制轉(zhuǎn)換洞斯。

什么是類型擦除?

不管泛型的類型傳入哪一種類型實(shí)參坑赡,對于java來說烙如,都會被當(dāng)成同一類處理,在內(nèi)存中也只占用一塊空間毅否,通俗一點(diǎn)來說亚铁,就是泛型之作用于代碼編譯階段,在編譯過程中螟加,對于正確檢驗(yàn)泛型結(jié)果后徘溢,會將泛型的信息擦除,也就是說捆探,成功編譯過后的class文件時(shí)不包含任何泛型信息的然爆。

6.反射

動(dòng)態(tài)代理和靜態(tài)代理

靜態(tài)代理很簡單,運(yùn)用的就是代理模式:聲明一個(gè)接口黍图,再分別實(shí)現(xiàn)一個(gè)真實(shí)的主題類和代理主題類曾雕,通過讓代理類持有真實(shí)主題類,從而控制用戶對真實(shí)主題的訪問助被。

動(dòng)態(tài)代理指的是在運(yùn)行時(shí)動(dòng)態(tài)生成代理類剖张,即代理類的字節(jié)碼在運(yùn)行時(shí)生成并載入當(dāng)前的ClassLoader切诀。

動(dòng)態(tài)代理的原理是使用反射,思路和上面的一致搔弄。

使用動(dòng)態(tài)代理的好處:

1.不需要為RealSubject寫一個(gè)形式完全一樣的代理類幅虑。

2.使用一些動(dòng)態(tài)代理的方法可以在運(yùn)行時(shí)制定代理類的邏輯,從而提升系統(tǒng)的靈活性顾犹。

java并發(fā)


java并發(fā)中考察頻率較高的有線程倒庵,線程池,鎖蹦渣,線程間的等待和喚醒哄芜,線程特性和阻塞隊(duì)列等。

1.線程

線程的狀態(tài)有哪些柬唯?下圖為一張狀態(tài)轉(zhuǎn)換圖



線程中wait和sleep的區(qū)別认臊?

wait方法即釋放cpu,又釋放鎖锄奢。

sleep方法只釋放cpu失晴,但是不釋放鎖。

進(jìn)程和線程的區(qū)別拘央?

進(jìn)程是資源分配的最小單位涂屁,線程是程序執(zhí)行的最小單位,一個(gè)進(jìn)程可以包含多個(gè)線程灰伟,在Android中拆又,一個(gè)進(jìn)程通常是一個(gè)App,App中會有一個(gè)主線程栏账,主線程可以用來操作界面元素帖族。如果有耗時(shí)操作,必須開啟子線程執(zhí)行挡爵。不然會導(dǎo)致ANR竖般。進(jìn)程間的數(shù)據(jù)是獨(dú)立的,線程間的數(shù)據(jù)可以共享茶鹃。

2.線程池

線程池地位十分重要涣雕,基本上涉及到跨線程的框架都是用到了線程池,比如OkHttp,RxJava,LiveData以及協(xié)程等闭翩。

與新建一個(gè)線程相比挣郭,線程池的特點(diǎn)?

1.節(jié)省開銷疗韵,線程池中的線程可以重復(fù)利用兑障。

2.速度快,任務(wù)來了就開始,省去創(chuàng)建線程的時(shí)間旺垒。

3.線程可控,線程數(shù)量可控和任務(wù)可控肤无。

4.功能強(qiáng)大先蒋,可以定時(shí)和重復(fù)執(zhí)行任務(wù)。

線程池中的幾個(gè)參數(shù)是什么意思宛渐,線程池的種類有哪些竞漾?

線程池的構(gòu)造函數(shù)如下:

publicThreadPoolExecutor(intcorePoolSize,

intmaximumPoolSize,

longkeepAliveTime,

TimeUnit?unit,

BlockingQueue?workQueue){

????this(corePoolSize,?maximumPoolSize,?keepAliveTime,?unit,?workQueue,

?????????????Executors.defaultThreadFactory(),?defaultHandler);

}


參數(shù)含義:

corePoolize:核心線程數(shù)量,不會釋放窥翩。

maximumPoolSize:允許使用的最大線程池?cái)?shù)量业岁,非核心線程數(shù)量,閑置時(shí)會釋放寇蚊。

keepAliveTime:閑置線程允許的最大閑置時(shí)間笔时。

unit:閑置時(shí)間的單位。

workQueue:阻塞隊(duì)列仗岸,不同的阻塞隊(duì)列有不同的特性允耿。

線程池分為四個(gè)類型:

CachedThreadPool:閑置線程超時(shí)會釋放,沒有閑置線程的情況下扒怖,每次都會創(chuàng)建新的線程较锡。

FixedThreadPool:線程池只能存放指定數(shù)量的線程池,線程不會釋放盗痒,可重復(fù)利用蚂蕴。

SingleThreadExecutor:單線程的線程池。

ScheduledThreadPool:可定時(shí)和重復(fù)執(zhí)行的線程池俯邓。

線程池的工作流程骡楼?


1.任務(wù)來了,優(yōu)先考慮核心線程看成。

2.核心線程滿了君编,進(jìn)入阻塞隊(duì)列。

3.阻塞隊(duì)列滿了川慌,考慮非核心線程吃嘿。

4.非核心線程滿了,再觸發(fā)拒絕任務(wù)梦重。

3.鎖

死鎖觸發(fā)的四大條件兑燥?

1.互斥鎖

2.請求與保持

3.不可剝奪

4.循環(huán)的請求與等待

synchronized關(guān)鍵字的使用?synchronized的參數(shù)放入對象和Class有什么區(qū)別琴拧?

synchronized關(guān)鍵字的用法:

1.修飾方法

2.修飾代碼塊降瞳,需要自己提供鎖對象,鎖對象包括對象本身,對象的Class和其他對象挣饥。

放入對象和Class的區(qū)別是:

1.鎖住的對象不同:成員方法鎖住的實(shí)例對象除师,靜態(tài)方法鎖住的是Class。

2.訪問控制不同:如果鎖住的是實(shí)例扔枫,只會針對同一個(gè)對象方法進(jìn)行同步訪問汛聚,多線程訪問同一個(gè)對象的synchronized代碼塊是串行的,訪問不同對象是并行的短荐。如果鎖住的是類倚舀,多線程訪問的不管是同一對象還是不同對象的synchronized代碼塊都是串行的。

synchronized的原理忍宋?

任何一個(gè)對象都有一個(gè)monitor與之相關(guān)聯(lián)痕貌,JVM基于進(jìn)入和退出mointor對象來實(shí)現(xiàn)代碼塊同步和方法同步,兩者實(shí)現(xiàn)細(xì)節(jié)不同:

1.代碼塊同步:在編譯字節(jié)碼的時(shí)候糠排,代碼塊起始的地方插入monitorenter指令舵稠,異常和代碼塊結(jié)束處插入monitorexit指令,線程在執(zhí)行monitorenter指令的時(shí)候嘗試獲取monitor對象的所有權(quán)乳讥。獲取 不到的情況下就是阻塞柱查。

2.方法同步:synchronized方法在method_info結(jié)構(gòu)有AAC_synchronized標(biāo)記,線程在執(zhí)行的時(shí)候獲取對應(yīng)的鎖云石,從而實(shí)現(xiàn)同步方法唉工。

synchronized和Lock的區(qū)別 ?

主要區(qū)別:

1.synchronized是Java中的關(guān)鍵字汹忠,是Java的內(nèi)置實(shí)現(xiàn)淋硝;Lock是Java中的接口。

2.synchronized遇到異常會釋放鎖宽菜;Lock需要在發(fā)生異常的時(shí)候調(diào)用成員方法Lock#unlock()方法谣膳。

3.synchronized是不可以中斷的,Lock可中斷铅乡。

4.synchronized不能去嘗試獲得鎖继谚,沒有獲得鎖就會被阻塞;Lock可以去嘗試獲得鎖阵幸,如果未獲得可以嘗試處理 其他邏輯花履。

5.synchronized多線程效率步入Lock,不過Java1.6以后已經(jīng)對synchronized進(jìn)行大量的優(yōu)化挚赊,所以性能上來講诡壁,其實(shí)差不了多少。

悲觀鎖和樂觀鎖的舉例荠割?以及他們的相關(guān)實(shí)現(xiàn)妹卿?

悲觀鎖和樂觀鎖的概念:

悲觀鎖:悲觀鎖會認(rèn)為,修改共享數(shù)據(jù)的時(shí)候其他線程也會修改數(shù)據(jù),因此只在不會受到其他線程干擾的情況下執(zhí)行夺克,這樣會導(dǎo)致其他有需要鎖的線程掛起箕宙,等到持有鎖的線程釋放鎖。

樂觀鎖:每次不加鎖铺纽,每次直接修改共享數(shù)據(jù)假設(shè)其他線程不會修改扒吁,如果發(fā)生沖突就直接重試,直到成功為止室囊。

舉例:

悲觀鎖:典型的悲觀鎖是獨(dú)占鎖,有synchronized魁索,ReentrantLock融撞。

樂觀鎖:典型的樂觀鎖是CAS,實(shí)現(xiàn)CAS的atomic為代表的一系列類。

CAS是什么粗蔚?底層原理尝偎?

CAS全程Compare And Set,核心的三個(gè)元素是:內(nèi)存位置鹏控,預(yù)期原值和新值致扯,執(zhí)行CAS的時(shí)候,會將內(nèi)存位置的值與預(yù)期原值進(jìn)行比較当辐,如果一致抖僵,就將原值更新為新值,否則就不更新缘揪。

底層原理:是借助CPU底層指令cmpxchg實(shí)現(xiàn)原子操作耍群。

4.線程間通訊

notify和notifyAll方法的區(qū)別?

notify隨機(jī)喚醒一個(gè)線程找筝,notifyAll喚醒所有等待的線程蹈垢,讓他們競爭鎖。

wait/notify和Condition類實(shí)現(xiàn)的等待通知有什么區(qū)別袖裕?

synchronized與wait/notify結(jié)合的等待通知只有一個(gè)條件曹抬,而Condition類可以實(shí)現(xiàn)多個(gè)條件等待。

5.多線程間的特性

多線程間的有序性急鳄,可見性和原子性是什么意思谤民?

原子性:執(zhí)行一個(gè)或者多個(gè)操作的時(shí)候,要么全部執(zhí)行攒岛,要么都不執(zhí)行赖临,并且中間過程中不會被打斷。Java中的原子性可以通過獨(dú)占鎖和CAS去保證灾锯。

可見性:指多線程訪問同一個(gè)變量的時(shí)候兢榨,一個(gè)線程修改了變量的值,其他線程能夠立刻看得到修改的值。鎖和volatile能夠保證可見性吵聪。

有序性:程序執(zhí)行的順序按照代碼先后的順序執(zhí)行凌那。鎖和volatile能夠保證有序性。

happens-before原則有哪些吟逝?

Java內(nèi)存模型具有一些先天的有序性帽蝶,它通常叫做happens-before原則。

如果兩個(gè)操作的先后順序不能通過happens-before原則推倒出來块攒,那就不能保證他們的先后執(zhí)行順序励稳。虛擬機(jī)就可以隨意打亂執(zhí)行命令。happens-before原則有:

1.程序次序規(guī)則:單線程程序的執(zhí)行結(jié)果得和看上去代碼執(zhí)行的結(jié)果要一致囱井。

2.鎖定規(guī)則:一個(gè)鎖的lock操作一定發(fā)生在上一個(gè)unlock操作之后驹尼。

3.volatile規(guī)則:對volatile變量的寫操作一定先行于后面對這個(gè)變量的對操作。

4.傳遞規(guī)則:A發(fā)生在B前面庞呕,B發(fā)生在C前面新翎,那么A一定發(fā)生在C前面。

5.線程啟動(dòng)規(guī)則:線程的start方法先行發(fā)生于線程中的每個(gè)動(dòng)作住练。

6.線程中斷規(guī)則:對線程的interrup操作先行發(fā)生于中斷線程的檢測代碼地啰。

7.線程終結(jié)原則:線程中所有的操作都先行發(fā)生于線程的終止檢測。

8.對象終止原則:一個(gè)對象的初始化先行發(fā)生于他的finalize()方法的執(zhí)行讲逛。

前四條規(guī)則比較重要亏吝。

volatile的原理?

可見性:如果對聲明了volatile的變量進(jìn)行寫操作的時(shí)候盏混,JVM會向處理器發(fā)送一條Lock前綴的指令顺呕,將這個(gè)變量所在緩存行的數(shù)據(jù)寫入到系統(tǒng)內(nèi)存。

多處理器的環(huán)境下括饶,其他處理器的緩存還是舊的株茶,為了保證各個(gè)處理器一致,會通過嗅探在總線上傳播的數(shù)據(jù)來檢測自己的數(shù)據(jù)是否過期图焰,如果過期启盛,會強(qiáng)制重新將系統(tǒng)內(nèi)存的數(shù)據(jù)讀取到處理器緩存。

有序性:Lock前綴的指令相當(dāng)于一個(gè)內(nèi)存柵欄技羔,它確保指令排序的時(shí)候僵闯,不會把后面的指令排到內(nèi)存柵欄的前面,也不會吧把前面的指令排到內(nèi)存柵欄的后面藤滥。

6.阻塞隊(duì)列

通常的阻塞隊(duì)列有哪幾種鳖粟?特點(diǎn)是什么?

ArrayBlockQueue:基于數(shù)組實(shí)現(xiàn)的有界的FIFO(先進(jìn)先出)阻塞隊(duì)列拙绊。

LinkedBlockQueue:基于鏈表實(shí)現(xiàn)的無界的FIFO(先進(jìn)先出)阻塞隊(duì)列向图。

SynchronousQueue:內(nèi)部沒有任何緩存的阻塞隊(duì)列泳秀。

PriorityBlockingQueue:具有優(yōu)先級的無限阻塞隊(duì)列。

ConcurrentHashMap的原理

數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)跟HashMap一樣榄攀,不做介紹嗜傅。

JDK1.8之前采用的是分段鎖,核心類是一個(gè)Segment檩赢,Segment繼承了ReentrantLock吕嘀,每個(gè)Segment對象管理若干個(gè)桶,多個(gè)線程訪問同一個(gè)元素的時(shí)候只能去競爭獲取鎖贞瞒。

JDK1.8采用了CAS+synchronized偶房,插入鍵值對的時(shí)候如果當(dāng)前桶中沒有Node節(jié)點(diǎn),使用CAS方式進(jìn)行更新军浆,如果有Node節(jié)點(diǎn)蝴悉,則使用synchronized的方式進(jìn)行更新。

二:網(wǎng)絡(luò)基礎(chǔ)知識


1.HTTP和HTTPS

HTTP是哪一層的協(xié)議瘾敢,常見的HTTP狀態(tài)碼有那些?分別代表什么意思尿这?

HTTP協(xié)議是應(yīng)用層協(xié)議簇抵。

常見的HTTP狀態(tài)碼有:

1xx請求已經(jīng)接收,繼續(xù)處理

2xx服務(wù)器已經(jīng)正確處理請求射众,比如200

3xx重定向碟摆,需要做進(jìn)一步的處理才能完成請求

4xx服務(wù)器無法理解的請求,比如404叨橱,訪問的資源不存在

5xx服務(wù)器收到請求以后典蜕,處理錯(cuò)誤


HTTP1.1和HTTP2有什么區(qū)別?

HTTP2.0基于1.1罗洗,HTTP2.0增加了:

1.二進(jìn)制格式:HTTP1.1使用純文本進(jìn)行通信愉舔,HTTP2.0使用二進(jìn)制進(jìn)行傳輸。

2.Head壓縮:對已經(jīng)發(fā)送的Header使用鍵值建立索引表伙菜,相同的Header使用索引表示轩缤。

3.服務(wù)器推送:服務(wù)器可以進(jìn)行主動(dòng)推送

4.多路復(fù)用:一個(gè)TCP連接可以劃分成多個(gè)流,每個(gè)流都會分配Id贩绕,客戶端可以借助流和服務(wù)端建立全雙工進(jìn)行通信火的,并且流具有優(yōu)先級。



HTTP和HTTPS有什么區(qū)別淑倾?

簡單來說馏鹤,HTTP和HTTPS的關(guān)系是:HTTPS=HTTP+SSL/TLS

區(qū)別如下:

HTTP作用于應(yīng)用層,使用80端口娇哆,起始地址是http://明文傳輸湃累,消息容易被攔截勃救,串改。

HTTPS作用域傳輸層脱茉,使用443端口剪芥,起始地址是https://,需要下載CA證書琴许,傳輸?shù)倪^程需要加密税肪,安全性高。

SSL/TLS的握手過程榜田?

這里借用《趣談網(wǎng)絡(luò)協(xié)議》的圖片:



HTTPS傳輸過程中是如何處理進(jìn)行加密的益兄?為什么又對稱加密的情況下仍然需要進(jìn)行非對稱加密?

過程和上圖類似箭券,一次獲取證書净捅,公鑰,最后生成對稱加密的鑰匙進(jìn)行對稱加密辩块。

對稱加密可以保證加密效率蛔六,但是不能解決秘鑰傳輸問題;非對稱加密可以解決傳輸問題废亭,但是效率不高国章。

2.TCP相關(guān)

TCP的三次握手過程,為什么需要三次豆村,而不是兩次或者四次液兽?


只發(fā)送兩次冒晰,服務(wù)端是不知道自己發(fā)送的消息能不能被客戶端接收到揪罕。

因?yàn)門CP握手是三次,所以此時(shí)雙方都已經(jīng)知道自己發(fā)送的消息能夠被對方收到驮樊,所以粗恢,第四次的發(fā)送就顯得多余了柑晒。

TCP的四次揮手過程?


大致意思:

Client:我要斷開連接了

Server:我收到你的消息了

Server:我也要斷開連接了

Client:收到你要斷開連接的消息了

之后Client等待兩個(gè)MSL(數(shù)據(jù)包在網(wǎng)絡(luò)上生存的最長時(shí)間)眷射,如果服務(wù)端沒有回消息就徹底斷開了敦迄。

TCP和UDP有什么區(qū)別?

TCP:基于字節(jié)流凭迹,面向連接罚屋,可靠,能夠進(jìn)行全雙工通信嗅绸,除此以外脾猛,還能進(jìn)行流量控制和擁塞控制,不過效率略低鱼鸠。

UDP:基于報(bào)文猛拴,面向無連接羹铅,不可靠,但是傳輸效率高愉昆。

總的來說职员,TCP使用于傳輸效率要求低,準(zhǔn)確性要求高或要求有連接跛溉。而UDP適用于對準(zhǔn)確性要求低焊切,傳輸效率要求較高的場景,比如語音通話芳室,直播等专肪。

TCP為什么是一種可靠的協(xié)議?如何做到流量控制和擁塞控制堪侯?

TCP可靠:是因?yàn)榭梢宰龅綌?shù)據(jù)包發(fā)送的有序嚎尤,無差錯(cuò)和無重復(fù)。

流量控制:是通過滑動(dòng)窗口實(shí)現(xiàn)的伍宦,因?yàn)榘l(fā)送方和接收方消息發(fā)送速度和接收速度不一定對等芽死,所以需要一個(gè)滑動(dòng)窗口來平衡處理效率,并且保證沒有差錯(cuò)和有序的接收數(shù)據(jù)包次洼。

擁塞控制:慢開始和擁塞避免关贵,快重傳和快恢復(fù)算法,這些算法主要是為了適應(yīng)網(wǎng)絡(luò)中的帶寬而做出的調(diào)整滓玖。

三:設(shè)計(jì)模式

1.六大原則

單一職責(zé):合理分配類和函數(shù)的職責(zé)

開閉原則:開放擴(kuò)展,關(guān)閉修改

里式替換:繼承

依賴倒置:面向接口

接口隔離:控制接口的粒度

迪米特:一個(gè)類應(yīng)該對其他的類了解最少

2.單例模式

單例的常用寫法有哪幾種质蕉?

懶漢模式:該模式主要問題是每次獲取實(shí)例都需要同步势篡,造成不必要的同步開銷。

public?classSingleInstance{

????private?static?SingleInstance?instance;

????private SingleInstance(){}

????publicstaticsynchronizedSingleInstancegetInstance(){

????????if(instance?==?null)?{

????????????instance?=?new?SingleInstance();

????????}

????????return?instance;

????}

}

DCL模式:高并發(fā)環(huán)境下可能發(fā)生問題

public?classSingleInstance{

????private?static?SingleInstance?instance;

????privateSingleInstance(){}

????publicstaticSingleInstancegetInstance(){

????????if(instance?==?null)?{

????????????synchronized?(SingleInstance.class)?{

????????????????if(instance?==?null)?{

????????????????????instance?=?new?SingleInstance();

????????????????}

????????????}

????????}

????????return?instance;

????}

}

靜態(tài)內(nèi)部類單例

public?classSingleInstance{

????privateSingleInstance(){}

????publicstaticSingleInstancegetInstance(){

????????return?SingleHolder.instance;

????}

????private?static?classSingleHolder{

????????private?static?final?SingleInstance?instance?=?new?SingleInstance();

????}

}

枚舉單例

public?enum?SingletonEnum?{

????INSTANCE

}

優(yōu)點(diǎn):線程安全和反序列化不會生成新的實(shí)例模暗。

DCL模式會有什么問題禁悠?

對象生成實(shí)例的過程中,大概會經(jīng)過以下過程:

1.為對象分配內(nèi)存空間

2.初始化對象中的成員變量

3.將對象指向分配的內(nèi)存空間(此時(shí)對象就不為null)

由于JVM會優(yōu)化指令順序兑宇,也就是說2和3的順序是不能保證的碍侦。在多線程的情況下,當(dāng)一個(gè)線程完成了1.3過程后隶糕,當(dāng)前線程的時(shí)間片已用完瓷产,這個(gè)時(shí)候會切換到另一個(gè)線程,另一個(gè)線程調(diào)用這個(gè)單例枚驻,會使用這個(gè)還沒初始化完成的實(shí)例濒旦。

解決方法是使用volatile關(guān)鍵字:


3.需要關(guān)注的設(shè)計(jì)模式

重點(diǎn)了解以下的幾種常用的設(shè)計(jì)模式:

1.工廠模式和抽象工廠模式:注意他們的區(qū)別。

2.責(zé)任鏈模式:View的事件分發(fā)和OkHttp的調(diào)用過程都使用到了責(zé)任鏈模式再登。

3.觀察者模式:重要性不言而喻尔邓。

4.代理模式:建議了解一下動(dòng)態(tài)代理晾剖。

4.MVC/MVP/MVVM

MVC,MVP和MVVM應(yīng)該是設(shè)計(jì)模式中考察頻率最高的知識點(diǎn)了,嚴(yán)格意義上來說梯嗽,他們不能算是設(shè)計(jì)模式齿尽,而是框架。

MVC灯节、MVP和MVVM是什么循头?

MVC:Model-View-Controller,是一種分層解耦的框架显晶,Model層提供本地?cái)?shù)據(jù)和網(wǎng)絡(luò)請求贷岸,View層處理視圖,Controller處理邏輯磷雇,存在問題是Controller層的劃分不明顯偿警,Model層和View層存在耦合。

MVP:Model_View_Presenter,是對MVC的升級唯笙,Model層和View層與MVC的意思一致螟蒸,但Model層和View層不再存在耦合,而是通過Presenter層這個(gè)橋梁進(jìn)行交流崩掘。

MVVM:Model_View_ViewModel:不同于上面的兩個(gè)框架七嫌,ViewModel持有數(shù)據(jù)狀態(tài),當(dāng)數(shù)據(jù)狀態(tài)改變的時(shí)候苞慢,會自動(dòng)通知View層進(jìn)行更新诵原。

MVC和MVP的區(qū)別是什么?

MVP是MVC的進(jìn)一步解耦挽放,簡單來講绍赛,在MVC中,View層既可以和Controller層交互辑畦,又可以和Model層交互吗蚌,而在MVP中,View層只能和Presenter層交互纯出,Model層也只能和Presenter層交互蚯妇,減少了View層和Model層的耦合,更容易定位錯(cuò)誤來源暂筝。

MVVM和MVP的最大區(qū)別在哪里箩言?

MVP中的每個(gè)方法都需要你去主動(dòng)調(diào)用,他其實(shí)是被動(dòng)的焕襟,而MVVM中有數(shù)據(jù)驅(qū)動(dòng)這個(gè)概念分扎,當(dāng)你的持有的數(shù)據(jù)狀態(tài)發(fā)生變更的時(shí)候,你的View可以監(jiān)聽到這個(gè)變化胧洒,從而主動(dòng)去更新畏吓,這其實(shí)是主動(dòng)的墨状。

ViewModel如何知道View層的生命周期?

事實(shí)上菲饼,如果你僅僅使用ViewModel肾砂,他是感知不了生命周期,他需要結(jié)合LiveData去感知生命周期宏悦,如果僅僅使用DataBinding去實(shí)現(xiàn)MVVM镐确,它對數(shù)據(jù)源使用了弱引用,所以一定程度上可以避免內(nèi)存泄露的發(fā)生饼煞。

四:Android基礎(chǔ)


1.Activity

Activity的四大啟動(dòng)模式源葫,以及應(yīng)用場景?

standard:標(biāo)準(zhǔn)模式砖瞧,每次都會在活動(dòng)棧中生成一個(gè)新的Activity實(shí)例息堂,通常我們使用的活動(dòng)都是標(biāo)準(zhǔn)模式。

singleTop:棧頂復(fù)用块促,如果Activity實(shí)例已經(jīng)存在棧頂荣堰,那么就不會再活動(dòng)棧中創(chuàng)建新的實(shí)例。比較常見的場景就是給通知跳轉(zhuǎn)的Activity設(shè)置竭翠,因?yàn)槟憧隙ú幌肭芭_Activity已經(jīng)是該Activity的情況下振坚,點(diǎn)擊通知,又創(chuàng)建一個(gè)同樣的Activity斋扰。

singleTask:棧內(nèi)復(fù)用渡八,如果Activity實(shí)例在當(dāng)前棧中已經(jīng)存在,就會將當(dāng)前Activity實(shí)例上面的其他Activity實(shí)例都移除出棧传货,常見于跳轉(zhuǎn)到主界面屎鳍。

singleInstance:單例模式,創(chuàng)建一個(gè)新的任務(wù)棧损离,這個(gè)活動(dòng)實(shí)例獨(dú)自處在這個(gè)活動(dòng)棧中哥艇。

2.屏幕適配

使用的屏幕適配方案绝编?原理是什么僻澎?

屏幕適配一般采用的頭條的屏幕適配方案。簡單來說十饥,以屏幕的一邊作為適配窟勃,通常是寬。

原理:設(shè)備像素px和設(shè)備獨(dú)立像素dp之間的關(guān)系逗堵。

px = dp*density

假設(shè)UI給的設(shè)計(jì)圖屏幕寬度基于360dp秉氧,那么設(shè)備寬的像素點(diǎn)已知,即px,dp也已知蜒秤,360dp汁咏,所以density = px/dp,之后根據(jù)這個(gè)修改系統(tǒng)中跟density相關(guān)的知識點(diǎn)即可亚斋。

3.Android消息機(jī)制

Android消息機(jī)制介紹?

Android消息機(jī)制中的四大概念:

ThreadLocal:當(dāng)前線程存儲的數(shù)據(jù)僅能從當(dāng)前線程取出攘滩。

MessageQueue:具有時(shí)間優(yōu)先級的消息隊(duì)列帅刊。

Looper:輪詢消息隊(duì)列,看是否有新的消息到來漂问。

Handler:具體處理邏輯的地方赖瞒。

過程:

1.準(zhǔn)備工作:創(chuàng)建Handler,如果是在子線程中創(chuàng)建蚤假,還需要調(diào)用Looper#prepare()栏饮,在Handler的構(gòu)造函數(shù)中,會綁定其中的Looper和MessageQueue磷仰。

2.發(fā)送消息:創(chuàng)建消息袍嬉,使用Handler發(fā)送。

3.進(jìn)入MessageQueue:因?yàn)镠andler中綁定這消息隊(duì)列芒划,所以Message很自然的被放進(jìn)消息隊(duì)列冬竟。

4.Looper輪詢消息隊(duì)列:Looper是一個(gè)死循環(huán),一直觀察有沒有新的消息到來民逼,之后從Message取出綁定的Handler泵殴,最后調(diào)用Handler中的處理邏輯,這一切都發(fā)生在Looper循環(huán)的線程拼苍,這也是Handler能夠在指定線程處理任務(wù)的原因笑诅。

Looper在主線程中死循環(huán)為什么沒有導(dǎo)致界面的卡頓?

1.導(dǎo)致卡死的是在UI線程中執(zhí)行耗時(shí)操作導(dǎo)致界面出現(xiàn)掉幀疮鲫,甚至ANR吆你。Looper.Loop()這個(gè)操作本身不會導(dǎo)致這個(gè)情況。

2.有人可能說俊犯,我在點(diǎn)擊事件中設(shè)置死循環(huán)會導(dǎo)致界面卡死妇多,同樣都是死循環(huán),不都一樣嗎燕侠?Looper會在沒有消息的時(shí)候阻塞當(dāng)前線程者祖,釋放CPU資源,等到有消息到來的時(shí)候绢彤,再喚醒主線程七问。

3.App進(jìn)程中是需要死循環(huán)的,如果循環(huán)結(jié)束的話茫舶,App進(jìn)程就結(jié)束了械巡。

建議閱讀:

《Android中為什么主線程不會因?yàn)長ooper.loop()里的死循環(huán)卡死?》

https://www.zhihu.com/question/34652589


IdleHandler介紹?

IdleHandler是在Handler空閑時(shí)處理空閑任務(wù)的一種機(jī)制讥耗。

執(zhí)行場景:

MessageQueue沒有消息有勾,隊(duì)列為空的時(shí)候。

MessageQueue屬于延遲消息古程,當(dāng)前沒有消息執(zhí)行的時(shí)候柠衅。

會不會發(fā)生死循環(huán):

肯定會,MessageQueue使用計(jì)數(shù)的方法保證一次調(diào)用MessageQueue#next方法只會使用一次的IdleHandler集合籍琳。

4.View事件分發(fā)機(jī)制和View繪制原理菲宴。

建議閱讀《Android開發(fā)藝術(shù)探索》第三章,很詳細(xì)趋急。

5.Bitmap

Bitmap的內(nèi)存計(jì)算方式喝峦?

在已知圖片的長和寬的像素情況下,影響內(nèi)存大小的因素會有資源文件位置和像素點(diǎn)大小呜达。

常見的像素點(diǎn)有:

ARGB_8888:4個(gè)字節(jié)

ARGB_4444,ARGB_565:2個(gè)字節(jié)

資源文件位置:

不同dpi對應(yīng)存放的文件夾


比如一個(gè)一張圖片的像素為180*180px谣蠢,dpi(設(shè)備獨(dú)立像素密度)為320,如果它僅僅存放在drawable-hdpi,則有

橫向像素點(diǎn)=180*320/240+0.5f = 240px

縱向像素點(diǎn)=180*320/240+0.5f? = 240px

如果它僅僅存放在drawable-xxhdpi,則有

橫向像素點(diǎn)=180*320/480+0.5f=120px

縱向像素點(diǎn)=180*320/480+0.5f=120px

所以查近,對于一張180*180px的圖片眉踱,設(shè)備dpi為320,資源圖片僅僅存在drawable-hdpi,像素點(diǎn)大小為ARGB_4444,最后生成的文件內(nèi)存大小為:

橫向像素點(diǎn)=180*320/240+0.5f=240px

縱向像素點(diǎn)=180*320/240+0.5f=240px

內(nèi)存大小=240*240*2 = 115200 byte 越等于 112.5kb

建議閱讀霜威;

《Android Bitmap的內(nèi)存大小是如何計(jì)算的谈喳?》

https://ivonhoe.github.io/2017/03/22/Bitmap&Memory/

Bitmap的高效加載?

Bitmap的高效加載在Glide中也用到了戈泼,思路:

1.獲取需要的長和寬婿禽,一般獲取控件的長和寬。

2.設(shè)置BitmapFactory.Options中的inJustDecodeBounds為true大猛,可以幫助我們在不加載內(nèi)存的方式獲得Bitmap的長和寬扭倾。

3.對需要的長和寬和Bitmap的長和寬進(jìn)行對比,從而獲得壓縮比例挽绩,放入BitmapFactory.Options中的inSampleSize屬性膛壹。

4.設(shè)置BitmapFactory.Options中的inJustDecodeBounds為false,將圖片加載進(jìn)內(nèi)存,進(jìn)而設(shè)置到控件中唉堪。

五:Android進(jìn)階


Android進(jìn)階中重點(diǎn)考察Android Framework,性能優(yōu)化和第三方框架模聋。

1.Binder

Binder的介紹?與其他IPC方式的優(yōu)缺點(diǎn)巨坊?

Binder是Android中特有的IPC方式撬槽,引用《Android開發(fā)藝術(shù)探索》中的話

從IPC角度來說此改,Binder是Android中的一種跨進(jìn)程通信方式趾撵,Binder還可以理解為虛擬的物理設(shè)備,它的設(shè)備驅(qū)動(dòng)是/dev/binder;從Android Frameword來講占调,Binder是Service Manager連接各種Manager和對應(yīng)的ManagerService的橋梁暂题,從面向?qū)ο蠛虲S模型來講,Client通過Binder和遠(yuǎn)程的Server進(jìn)行通訊究珊。

基于Binder,Android還實(shí)現(xiàn)了其他的IPC方式薪者,比如AIDL,Messenger和ContentProvider。與其他IPC比較:

效率高:出了內(nèi)存共享外剿涮,其他IPC都需要進(jìn)行兩次數(shù)據(jù)拷貝言津,而因?yàn)锽inder使用內(nèi)存映射的關(guān)系,僅需要一次數(shù)據(jù)拷貝取试。

安全性好:接收方可以從數(shù)據(jù)包中獲取發(fā)送發(fā)的進(jìn)程Id和用戶Id悬槽,方便驗(yàn)證發(fā)送方的身份,其他IPC想要實(shí)驗(yàn)只能夠主動(dòng)存入瞬浓,但是這有可能在發(fā)送的過程中被修改初婆。

Binder的通信過程?Binder的原理猿棉?


其實(shí)這個(gè)過程也可以從AIDL生成的代碼中看出磅叛。

原理:


Binder的結(jié)構(gòu):

Client:服務(wù)的請求方。

Server:服務(wù)的提供方萨赁。

Service Manager:為Server提供Binder的注冊服務(wù)弊琴,為Client提供Binder的查詢服務(wù),Server杖爽、Client和Service Manager的通訊都是通過Binder访雪。

Binder驅(qū)動(dòng):負(fù)責(zé)Binder通信機(jī)制的建立,提供一系列底層支持掂林。

從上圖中臣缀,Binder通信的過程是這樣的:

1.Server在Service Manager中注冊:Server進(jìn)程在創(chuàng)建的時(shí)候,也會創(chuàng)建對應(yīng)的Binder實(shí)體泻帮,如果要提供服務(wù)給Client精置,就必須為Binder實(shí)體注冊一個(gè)名字。

2.Client通過Service Manager獲取服務(wù):Client知道服務(wù)中Binder實(shí)體的名字后锣杂,通過名字從Service Manager獲取Binder實(shí)體的引用脂倦。

3.Client使用服務(wù)與Server進(jìn)行通信:Client通過調(diào)用Binder實(shí)體與Server進(jìn)行通信。

更詳細(xì)一點(diǎn)元莫?

Binder通信的實(shí)質(zhì)是利用內(nèi)存映射赖阻,將用戶進(jìn)程的內(nèi)存地址和內(nèi)核的內(nèi)存地址映射為同一塊物理地址,也就是說他們使用的同一塊物理空間踱蠢,每次創(chuàng)建Binder的時(shí)候大概分配128的空間火欧。數(shù)據(jù)進(jìn)行傳輸?shù)臅r(shí)候棋电,從這個(gè)內(nèi)存空間分配一點(diǎn),用完了再釋放即可苇侵。

2.序列化

Android有那些序列化方式赶盔?

為了解決Android中內(nèi)存序列化速度過慢的問題,Android使用了Parcelable.


3.Framework

Zygote孕育進(jìn)程過程榆浓?


Activity的啟動(dòng)過程于未?


建議閱讀:

《3分鐘看懂Activity啟動(dòng)流程》

http://www.reibang.com/p/9ecea420eb52

App的啟動(dòng)過程?

介紹下App進(jìn)程和System Server進(jìn)程如何聯(lián)系:


App進(jìn)程

ActivityThread:依賴于UI線程陡鹃,實(shí)際處理與AMS中交互的工作烘浦。

ActivityManagerService:負(fù)責(zé)Activity,Service等的生命周期工作。

ApplicationThread:System Server進(jìn)程中ApplicationThreadProxy的服務(wù)端萍鲸,幫助System Server進(jìn)程跟App進(jìn)程交流谎倔。

System Server:Android核心的進(jìn)程,掌管著Android系統(tǒng)中各種重要的服務(wù)猿推。


具體過程:

1.用戶點(diǎn)擊App圖標(biāo)片习,Lanuacher進(jìn)程通過Binder聯(lián)系到System Server進(jìn)程發(fā)起startActivity。

2.System Server通過Socket聯(lián)系到Zygote,fork出一個(gè)新的App進(jìn)程蹬叭。

3.創(chuàng)建一個(gè)新的App進(jìn)程以后藕咏,Zygote啟動(dòng)App進(jìn)程的ActivityThread#main()方法。

4.在ActivityThread中秽五,調(diào)用AMS進(jìn)行ApplicationThread的綁定孽查。

5.AMS發(fā)送創(chuàng)建Application的消息給ApplicationThread,進(jìn)而轉(zhuǎn)交給ActivityThread中的H,他是一個(gè)Handler坦喘,接著進(jìn)行Application的創(chuàng)建工作盲再。

6.AMS以同樣的方式創(chuàng)建Activity,接著就是大家熟悉的創(chuàng)建Activity的工作了瓣铣。

APK的安裝過程答朋?

建議閱讀:

《Android Apk安裝過程分析》

http://www.reibang.com/p/953475cea991

Activity啟動(dòng)過程跟Window的關(guān)系?

建議閱讀:

《簡析Window棠笑、Activity梦碗、DecorView以及ViewRoot之間的錯(cuò)綜關(guān)系》

https://juejin.im/post/5dac6aa2518825630e5d17da

Activity,Window,ViewRoot和DecorView之間的關(guān)系?

建議閱讀:

《總結(jié)UI原理和高級的UI優(yōu)化方式》

http://www.reibang.com/p/8766babc40e0


4.Context

關(guān)于Context的理解蓖救?

建議閱讀:

《Android Context 上下文 你必須知道的一切》

https://blog.csdn.net/lmj623565791/article/details/40481055

5.斷點(diǎn)續(xù)傳

多線程斷點(diǎn)續(xù)傳洪规?

基礎(chǔ)知識:

1.Http基礎(chǔ):在Http請求中,可以加入請求頭Range循捺,下載特定區(qū)間的文件數(shù)斩例。

2.RandomAccessFile:支持隨機(jī)訪問,可以從指定位置進(jìn)行數(shù)據(jù)的讀寫从橘。

6.性能優(yōu)化

平時(shí)做了哪些性能優(yōu)化念赶?

建議閱讀:

《Android 性能優(yōu)化最佳實(shí)踐》

https://juejin.im/post/5b50b017f265da0f7b2f649c

7.第三方庫

一定要在熟練使用后再去查看原理础钠。

Glide

Glide考察的頻率挺高的,常見的問題有:

1.Glide和其他圖片加載框架的比較晶乔?

2.如何設(shè)計(jì)一個(gè)圖片加載框架?

3.Glide緩存實(shí)現(xiàn)機(jī)制牺勾?

4.Glide如何處理生命周期正罢?

建議閱讀:

《Glide最全解析》

https://blog.csdn.net/sinyu890807/category_9268670.html

《面試官:簡歷上最好不要寫Glide,不是問源碼那么簡單》

https://juejin.im/post/5dbeda27e51d452a161e00c8


OkHttp

OkHttp常見知識點(diǎn):

1.責(zé)任鏈模式

2.interceptors和networkInterceptors的區(qū)別驻民?

建議看一遍源碼翻具,過程并不復(fù)雜。

Retrofit

Retrofit常見問題:

1.設(shè)計(jì)模式和封層解耦的理念

2.動(dòng)態(tài)代理

建議看一遍源碼回还,過程并不復(fù)雜裆泳。

RxJava

RxJava難在各種操作符,我們了解一下大致的設(shè)計(jì)思想即可柠硕。

建議閱讀一些RxJava的文章工禾。

Android Jetpack(非必須)

我們主要閱讀了Android Jetpack中以下庫的源碼:

1.Lifecycle:觀察者模式,組件生命周期中發(fā)送事件蝗柔。

2.DataBinding:核心就是利用LiveData或者Observable xxx 實(shí)現(xiàn)的觀察者模式闻葵,對16進(jìn)制的狀態(tài)位更新,之后根據(jù)這個(gè)狀態(tài)位取更新對應(yīng)的內(nèi)容癣丧。

3.LiveData:觀察者模式槽畔,事件的生產(chǎn)消費(fèi)模型。

4.ViewModel:借用Activity異常銷毀時(shí)存儲隱藏Fragment的機(jī)制存儲ViewModel胁编,保證數(shù)據(jù)的生命周期盡可能的延長厢钧。

5.Paging:設(shè)計(jì)思想。

建議閱讀:

《Android Jetpack源碼分析系列》

https://blog.csdn.net/mq2553299/column/info/24151

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嬉橙,一起剝皮案震驚了整個(gè)濱河市早直,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌市框,老刑警劉巖莽鸿,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拾给,居然都是意外死亡祥得,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門蒋得,熙熙樓的掌柜王于貴愁眉苦臉地迎上來级及,“玉大人,你說我怎么就攤上這事额衙∫梗” “怎么了怕吴?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長县踢。 經(jīng)常有香客問我转绷,道長,這世上最難降的妖魔是什么硼啤? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任议经,我火速辦了婚禮,結(jié)果婚禮上谴返,老公的妹妹穿的比我還像新娘煞肾。我一直安慰自己,他們只是感情好嗓袱,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布籍救。 她就那樣靜靜地躺著,像睡著了一般渠抹。 火紅的嫁衣襯著肌膚如雪蝙昙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天梧却,我揣著相機(jī)與錄音耸黑,去河邊找鬼。 笑死篮幢,一個(gè)胖子當(dāng)著我的面吹牛大刊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播三椿,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼缺菌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搜锰?” 一聲冷哼從身側(cè)響起伴郁,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蛋叼,沒想到半個(gè)月后焊傅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狈涮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年狐胎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歌馍。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡握巢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出松却,到底是詐尸還是另有隱情暴浦,我是刑警寧澤溅话,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站歌焦,受9級特大地震影響飞几,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜独撇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一屑墨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧券勺,春花似錦绪钥、人聲如沸灿里。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匣吊。三九已至儒拂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間色鸳,已是汗流浹背社痛。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留命雀,地道東北人蒜哀。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像吏砂,于是被迫代替她去往敵國和親撵儿。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359