Android常問的面試題(二)

(一)圖片

1谣旁、圖片庫對比

2、LRUCache原理

LruCache是個泛型類滋早,主要原理是:把最近使用的對象用強(qiáng)引用存儲在LinkedHashMap中榄审,當(dāng)緩存滿時,把最近最少使用的對象從內(nèi)存中移除杆麸,并提供get/put方法完成緩存的獲取和添加搁进。LruCache是線程安全的浪感,因為使用了synchronized關(guān)鍵字。

當(dāng)調(diào)用put()方法饼问,將元素加到鏈表頭影兽,如果鏈表中沒有該元素,大小不變莱革,如果沒有峻堰,需調(diào)用trimToSize方法判斷是否超過最大緩存量,trimToSize()方法中有一個while(true)死循環(huán)盅视,如果緩存大小大于最大的緩存值,會不斷刪除LinkedHashMap中隊尾的元素茧妒,即最少訪問的,直到緩存大小小于最大緩存值左冬。當(dāng)調(diào)用LruCache的get方法時桐筏,LinkedHashMap會調(diào)用recordAccess方法將此元素加到鏈表頭部。

3拇砰、圖片加載原理

4梅忌、自己去實現(xiàn)圖片庫,怎么做除破?

5牧氮、Glide源碼解析

1)Glide.with(context)創(chuàng)建了一個RequestManager,同時實現(xiàn)加載圖片與組件生命周期綁定:在Activity上創(chuàng)建一個透明的ReuqestManagerFragment加入到FragmentManager中瑰枫,通過添加的Fragment感知Activty\Fragment的生命周期踱葛。因為添加到Activity中的Fragment會跟隨Activity的生命周期。在RequestManagerFragment中的相應(yīng)生命周期方法中通過liftcycle傳遞給在lifecycle中注冊的LifecycleListener

2)RequestManager.load(url) 創(chuàng)建了一個RequestBuilder<T>對象 T可以是Drawable對象或是ResourceType等

3) RequestBuilder.into(view)

-->into(glideContext.buildImageViewTarget(view, transcodeClass))返回的是一個DrawableImageViewTarget, Target用來最終展示圖片的光坝,buildImageViewTarget-->ImageViewTargetFactory.buildTarget()根據(jù)傳入class參數(shù)不同構(gòu)建不同的Target對象尸诽,這個Class是根據(jù)構(gòu)建Glide時是否調(diào)用了asBitmap()方法,如果調(diào)用了會構(gòu)建出BitmapImageViewTarget盯另,否則構(gòu)建的是GlideDrawableImageViewTarget對象性含。

-->GenericRequestBuilder.into(Target),該方法進(jìn)行了構(gòu)建Request,并用RequestTracker.runRequest()

??? Request request = buildRequest(target);//構(gòu)建Request對象鸳惯,Request是用來發(fā)出加載圖片的商蕴,它調(diào)用了buildRequestRecursive()方法以,內(nèi)部調(diào)用了GenericRequest.obtain()方法

??? target.setRequest(request);

??? lifecycle.addListener(target);

??? requestTracker.runRequest(request);//判斷Glide當(dāng)前是不是處于暫停狀態(tài)芝发,若不是則調(diào)用Request.begin()方法來執(zhí)行Request绪商,否則將Request添加到待執(zhí)行隊列里,等暫停態(tài)解除了后再執(zhí)行

-->GenericRequest.begin()

1)onSizeReady()--> Engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,

??????????? priority, isMemoryCacheable, diskCacheStrategy, this) --> a)先構(gòu)建EngineKey; b) loadFromCache從緩存中獲取EngineResource辅鲸,如果緩存中獲取到cache就調(diào)用cb.onResourceReady(cached)格郁; c)如果緩存中不存在調(diào)用loadFromActiveResources從active中獲取,如果獲取到就調(diào)用cb.onResourceReady(cached);d)如果active中也不存在理张,調(diào)用EngineJob.start(EngineRunnable), 從而調(diào)用decodeFromSource()/decodeFromCache()-->如果是調(diào)用decodeFromSource()-->ImageVideoFetcher.loadData()-->HttpUrlFetcher()調(diào)用HttpUrlConnection進(jìn)行網(wǎng)絡(luò)請求資源-->得于InputStream()后,調(diào)用decodeFromSourceData()-->loadProvider.getSourceDecoder().decode()方法解碼-->GifBitmapWrapperResourceDecoder.decode()-->decodeStream()先從流中讀取2個字節(jié)判斷是GIF還是普通圖赫蛇,若是GIF調(diào)用decodeGifWrapper()來解碼,若是普通靜圖則調(diào)用decodeBitmapWrapper()來解碼-->bitmapDecoder.decode()

6雾叭、Glide使用什么緩存悟耘?

1) 內(nèi)存緩存:LruResourceCache(memory)+弱引用activeResources

Map<Key, WeakReference<EngineResource<?>>> activeResources正在使用的資源,當(dāng)acquired變量大于0织狐,說明圖片正在使用暂幼,放到activeResources弱引用緩存中,經(jīng)過release()后移迫,acquired=0,說明圖片不再使用旺嬉,會把它放進(jìn)LruResourceCache中

2)磁盤緩存:DiskLruCache,這里分為Source(原始圖片)和Result(轉(zhuǎn)換后的圖片)

第一次獲取圖片,肯定網(wǎng)絡(luò)取厨埋,然后存active\disk中澄阳,再把圖片顯示出來久又,第二次讀取相同的圖片聚霜,并加載到相同大小的imageview中沟饥,會先從memory中取,沒有再去active中獲取废赞。如果activity執(zhí)行到onStop時徽龟,圖片被回收,active中的資源會被保存到memory中唉地,active中的資源被回收据悔。當(dāng)再次加載圖片時,會從memory中取耘沼,再放入active中极颓,并將memory中對應(yīng)的資源回收。

之所以需要activeResources耕拷,它是一個隨時可能被回收的資源讼昆,memory的強(qiáng)引用頻繁讀寫可能造成內(nèi)存激增頻繁GC,而造成內(nèi)存抖動骚烧。資源在使用過程中保存在activeResources中,而activeResources是弱引用闰围,隨時被系統(tǒng)回收赃绊,不會造成內(nèi)存過多使用和泄漏。

7羡榴、Glide內(nèi)存緩存如何控制大斜滩椤?

Glide內(nèi)存緩存最大空間(maxSize)=每個進(jìn)程可用最大內(nèi)存*0.4(低配手機(jī)是?? 每個進(jìn)程可用最大內(nèi)存*0.33)

磁盤緩存大小是250MB?? int DEFAULT_DISK_CACHE_SIZE = 250 * 1024 * 1024;

(二)網(wǎng)絡(luò)和安全機(jī)制

??? 網(wǎng)絡(luò)框架對比和源碼分析

??? 自己去設(shè)計網(wǎng)絡(luò)請求框架,怎么做忠售?

??? okhttp源碼

??? 網(wǎng)絡(luò)請求緩存處理传惠,okhttp如何處理網(wǎng)絡(luò)緩存的

(1)網(wǎng)絡(luò)緩存優(yōu)先考慮強(qiáng)制緩存,再考慮對比緩存

??? 首先判斷強(qiáng)制緩存中的數(shù)據(jù)的是否在有效期內(nèi)稻扬。如果在有效期卦方,則直接使用緩存。如果過了有效期泰佳,則進(jìn)入對比緩存盼砍。

??? 在對比緩存過程中,判斷ETag是否有變動逝她,如果服務(wù)端返回沒有變動浇坐,說明資源未改變,使用緩存黔宛。如果有變動近刘,判斷Last-Modified。

??? 判斷Last-Modified臀晃,如果服務(wù)端對比資源的上次修改時間沒有變化跌宛,則使用緩存,否則重新請求服務(wù)端的數(shù)據(jù)积仗,并作緩存工作疆拘。

(2)okhttp緩存

開啟使用Okhttp的緩存其實很簡單,只需要給OkHttpClient對象設(shè)置一個Cache對象即可寂曹,創(chuàng)建一個Cache時指定緩存保存的目錄和緩存最大的大小即可哎迄。

??? //新建一個cache,指定目錄為外部目錄下的okhttp_cache目錄隆圆,大小為100M

??? Cache cache = new Cache(new File(Environment.getExternalStorageDirectory() + "/okhttp_cache/"), 100 * 1024 * 1024);

??? //將cache設(shè)置到OkHttpClient中漱挚,這樣緩存就開始生效了。

??? OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();

相關(guān)的類有:

1)CacheControl( HTTP中的Cache-Control和Pragma緩存控制):指定緩存規(guī)則

2)Cache(緩存類)

3)DiskLruCache(文件化的LRU緩存類)

(1)讀取緩存:先獲限OkHttpClient的Cache緩存對象渺氧,就是上面創(chuàng)建OkHttpClient設(shè)置的Cahce; 傳Request請求到Cache的get方法查找緩存響應(yīng)數(shù)據(jù)Response旨涝;構(gòu)造一個緩存策略,再調(diào)用它的get去決策使用網(wǎng)絡(luò)請求還是緩存響應(yīng)侣背。若使用緩存白华,它的cacheResponse不為空,networkRequest為空,用緩存構(gòu)造響應(yīng)直接返回贩耐。若使用請求弧腥,則cacheResponse為空,networkRequest不為空,開始網(wǎng)絡(luò)請求流程潮太。

Cache的get獲取緩存方法管搪,計算request的key值(請求url進(jìn)行md5加密)虾攻,根據(jù)key值去DisLruCache查找是否存在緩存內(nèi)容,存則則創(chuàng)建繪存Entry實體更鲁。ENTRY_METADATA代表響應(yīng)頭信息霎箍,ENTRY_BODY代表響應(yīng)體信息。如果緩存存在澡为,在指定目錄下會有兩個文件****.0??? *****.1分別存儲某個請求緩存響應(yīng)頭和響應(yīng)體信息漂坏。

CacheStrategy的get方法:1)若緩存響應(yīng)為空或 2)請求是https但緩存響應(yīng)沒有握手信息;3)請求和緩存響應(yīng)都是不可緩存的缀壤;4)請求是onCache樊拓,并且又包含if-Modified-Since或If-None-Match則不使用緩存; 再計算請求有效時間是否符合響應(yīng)的過期時間塘慕,若響應(yīng)在有效范圍內(nèi)筋夏,則緩存策略使用緩存,否則創(chuàng)建一個新的有條件的請求图呢,返回有條件的緩存策略条篷。

(2)存儲緩存流程:從HttpEngine的readResponse()發(fā)送請求開始,判斷hasBody(userResponse),如果緩存的話蛤织,maybeCache()緩存響應(yīng)頭信息赴叹,unzip(cacheWritingResponse(storeRequest, userResponse))緩存響應(yīng)體。

??? 從網(wǎng)絡(luò)加載一個10M的圖片指蚜,說下注意事項

??? TCP的3次握手和四次揮手

??? TCP與UDP的區(qū)別

??? TCP與UDP的應(yīng)用

??? HTTP協(xié)議

??? HTTP1.0與2.0的區(qū)別

??? HTTP報文結(jié)構(gòu)

??? HTTP與HTTPS的區(qū)別以及如何實現(xiàn)安全性

??? 如何驗證證書的合法性?

??? https中哪里用了對稱加密乞巧,哪里用了非對稱加密,對加密算法(如RSA)等是否有了解?

??? client如何確定自己發(fā)送的消息被server收到?

??? 談?wù)勀銓ebSocket的理解

??? WebSocket與socket的區(qū)別

??? 談?wù)勀銓Π沧亢灻睦斫狻?/p>

??? 請解釋安卓為啥要加簽名機(jī)制?

??? 視頻加密傳輸

??? App 是如何沙箱化摊鸡,為什么要這么做绽媒?

??? 權(quán)限管理系統(tǒng)(底層的權(quán)限是如何進(jìn)行 grant 的)?

(三)數(shù)據(jù)庫

??? sqlite升級免猾,增加字段的語句

??? 數(shù)據(jù)庫框架對比和源碼分析

??? 數(shù)據(jù)庫的優(yōu)化

??? 數(shù)據(jù)庫數(shù)據(jù)遷移問題

(四)算法

??? 排序算法有哪些是辕?

??? 最快的排序算法是哪個?

??? 手寫一個冒泡排序

??? 手寫快速排序代碼

??? 快速排序的過程猎提、時間復(fù)雜度获三、空間復(fù)雜度

??? 手寫堆排序

??? 堆排序過程、時間復(fù)雜度及空間復(fù)雜度

??? 寫出你所知道的排序算法及時空復(fù)雜度锨苏,穩(wěn)定性

??? 二叉樹給出根節(jié)點和目標(biāo)節(jié)點疙教,找出從根節(jié)點到目標(biāo)節(jié)點的路徑

??? 給阿里2萬多名員工按年齡排序應(yīng)該選擇哪個算法?

??? GC算法(各種算法的優(yōu)缺點以及應(yīng)用場景)

??? 蟻群算法與蒙特卡洛算法

??? 子串包含問題(KMP 算法)寫代碼實現(xiàn)

??? 一個無序蚓炬,不重復(fù)數(shù)組松逊,輸出N個元素,使得N個元素的和相加為M肯夏,給出時間復(fù)雜度、空間復(fù)雜度。手寫算法

??? 萬億級別的兩個URL文件A和B驯击,如何求出A和B的差集C(提示:Bit映射->hash分組->多文件讀寫效率->磁盤尋址以及應(yīng)用層面對尋址的優(yōu)化)

??? 百度POI中如何試下查找最近的商家功能(提示:坐標(biāo)鏡像+R樹)烁兰。

??? 兩個不重復(fù)的數(shù)組集合中,求共同的元素徊都。

??? 兩個不重復(fù)的數(shù)組集合中沪斟,這兩個集合都是海量數(shù)據(jù),內(nèi)存中放不下暇矫,怎么求共同的元素主之?

??? 一個文件中有100萬個整數(shù),由空格分開李根,在程序中判斷用戶輸入的整數(shù)是否在此文件中槽奕。說出最優(yōu)的方法

??? 一張Bitmap所占內(nèi)存以及內(nèi)存占用的計算

一張圖片(bitmap)占用的內(nèi)存影響因素:圖片原始長、寬房轿,手機(jī)屏幕密度粤攒,圖片存放路徑下的密度,單位像素占用字節(jié)數(shù)

bitmapSize=圖片長度*(inTargetDensity手機(jī)的density / inDensity圖片存放目錄的density)*寬度*(手機(jī)的inTargetDensity / inDensity目標(biāo)存放目錄的density)*單位像素占用的字節(jié)數(shù)(圖片長寬單位是像素)

1)圖片長寬單位是像素:單位像素字節(jié)數(shù)由其參數(shù)BitmapFactory.Options.inPreferredConfig變量決定囱持,它是Bitmap.Config類型夯接,包括以下幾種值:ALPHA_8圖片只有alpha值,占用一個字節(jié)纷妆;ARGB_4444 一個像素占用2個字節(jié),A\R\G\B各占4bits盔几;ARGB_8888一個像素占用4個字節(jié),A\R\G\B各占8bits(高質(zhì)量圖片格式掩幢,bitmap默認(rèn)格式)逊拍;ARGB_565一個像素占用2字節(jié),不支持透明和半透明粒蜈,R占5bit, Green占6bit, Blue占用5bit. 從Android4.0開始該項無效顺献。

2) inTargetDensity 手機(jī)的屏幕密度(跟手機(jī)分辨率有關(guān)系)

inDensity原始資源密度(mdpi:160;?? hdpi:240;?? xhdpi:320;?? xxhdpi:480; xxxhdpi:640)

當(dāng)Bitmap對象在不使用時,應(yīng)該先調(diào)用recycle()枯怖,再將它設(shè)置為null注整,雖然Bitmap在被回收時可通過BitmapFinalizer來回收內(nèi)存。但只有系統(tǒng)垃圾回收時才會回收度硝。Android4.0之前肿轨,Bitmap內(nèi)存分配在Native堆中,Android4.0開始蕊程,Bitmap的內(nèi)存分配在dalvik堆中椒袍,即Java堆中,調(diào)用recycle()并不能立即釋放Native內(nèi)存藻茂。

??? 2000萬個整數(shù)驹暑,找出第五十大的數(shù)字玫恳?

??? 燒一根不均勻的繩,從頭燒到尾總共需要1個小時∮欧現(xiàn)在有若干條材質(zhì)相同的繩子京办,問如何用燒繩的方法來計時一個小時十五分鐘呢?

??? 求1000以內(nèi)的水仙花數(shù)以及40億以內(nèi)的水仙花數(shù)

??? 5枚硬幣帆焕,2正3反如何劃分為兩堆然后通過翻轉(zhuǎn)讓兩堆中正面向上的硬8幣和反面向上的硬幣個數(shù)相同

??? 時針走一圈惭婿,時針分針重合幾次

??? N*N的方格紙,里面有多少個正方形

??? x個蘋果,一天只能吃一個叶雹、兩個财饥、或者三個,問多少天可以吃完折晦?

(五)插件化钥星、模塊化、組件化筋遭、熱修復(fù)打颤、增量更新、Gradle

??? 對熱修復(fù)和插件化的理解

??? 插件化原理分析

??? 模塊化實現(xiàn)(好處漓滔,原因)

??? 熱修復(fù),插件化

??? 項目組件化的理解

??? 描述清點擊 Android Studio 的 build 按鈕后發(fā)生了什么

(六)架構(gòu)設(shè)計和設(shè)計模式

??? 談?wù)勀銓ndroid設(shè)計模式的理解

??? MVC MVP MVVM原理和區(qū)別

??? 你所知道的設(shè)計模式有哪些编饺?

??? 項目中常用的設(shè)計模式

??? 手寫生產(chǎn)者/消費者模式

??? 寫出觀察者模式的代碼

??? 適配器模式,裝飾者模式响驴,外觀模式的異同透且?

??? 用到的一些開源框架,介紹一個看過源碼的豁鲤,內(nèi)部實現(xiàn)過程秽誊。

??? 談?wù)剬xJava的理解

RxJava是基于響應(yīng)式編程,基于事件流琳骡、實現(xiàn)異步操(類似于Android中的AsyncTask锅论、Handler作用)作的庫,基于事件流的鏈?zhǔn)秸{(diào)用楣号,使得RxJava邏輯簡潔最易、使用簡單。RxJava原理是基于一種擴(kuò)展的觀察者模式炫狱,有四種角色:被觀察者Observable 觀察者Observer 訂閱subscribe 事件Event藻懒。RxJava原理可總結(jié)為:被觀察者Observable通過訂閱(subscribe)按順序發(fā)送事件(Emitter)給觀察者(Observer), 觀察者按順序接收事件&作出相應(yīng)的響應(yīng)動作视译。

RxJava中的操作符:

1)defer():直到有觀察者(Observer)訂閱時嬉荆,才會動態(tài)創(chuàng)建被觀察者對象(Observer)&發(fā)送事件,通過Observer工廠方法創(chuàng)建被觀察者對象酷含,每次訂閱后鄙早,都會得到一個剛創(chuàng)建的最新的Observer對象汪茧,可以確保Observer對象里的數(shù)據(jù)是最新的。defer()方法只會定義Observable對象蝶锋,只有訂閱操作才會創(chuàng)建對象陆爽。

??? Observable<T> observable = Observable.defer(new Callable<ObservableSource<? extends T>>() {

??????? @Override

??????? public ObservableSource<? extends T> call() throws Exception {

??????????? return Observable.just();

??????? }

??? }

2)timer() 快速創(chuàng)建一個被觀察者(Observable)什往,延遲指定時間后扳缕,再發(fā)送事件

??? Observable.timer(2, TimeUnit.SECONDS)//也可以自定義線程timer(long, TimeUnit, Scheduler)

??????? .subscribe(new Observer<Long>() {

??????????? @Override

??????????? public void onSubscribe(Disposable d) {

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

??????????? ...

???????? });

3) interval() intervalRange() 快速創(chuàng)建一個被觀察者對象(Observable),每隔指定時間就發(fā)送事件

??? //interval三個參數(shù)别威,參數(shù)1:第一次延遲時間? 參數(shù)2:間隔時間數(shù)字?? 參數(shù)3:時間單位

??? Observable.interval(3, 1, TimeUnit.SECONDS).subscribe();

??? //intervalRange五個參數(shù)躯舔,參數(shù)1:事件序列起始點? 參數(shù)2:事件數(shù)量? 參數(shù)3:第一次延遲時間 參數(shù)4:間隔時間數(shù)字?? 參數(shù)5:時間單位

??? Observable.intervalRange(3, 10, 2, 1, TimeUnit.SECONDS).subscribe();

??? RxJava的功能與原理實現(xiàn)

Rxjava發(fā)送事件步驟:

1)創(chuàng)建被觀察者對象Observable&定義需要發(fā)送的事件

??? Observable.create(new ObservableOnSubscribe<T>(){

??????? @Override

??????? public void subscribe(ObservableEmitter<T> emitter) throws Exception {

??????????? //定義發(fā)送事件的行為

??????? }

??? });

Observable.create()方法實際創(chuàng)建了一個ObservableCreate對象,它是Observable的子類省古,傳入一個ObservableOnSubscribe對象粥庄,復(fù)寫了發(fā)送事件行為的subscribe()方法。

2)創(chuàng)建觀察者對象Observer&定義響應(yīng)事件的行為

??? Observer observer = new Observer<T>() {

??????? @Override

??????? public void onSubscribe(Disposable d){//Disposable對象可用于結(jié)束事件

??????????? //默認(rèn)最先調(diào)用

??????? }

??????? @Override

??????? public void onNext(T t){

??????? }

??????? @Override

??????? public void onError(Throwable d){

??????? }

??????? @Override

??????? public void onComplete(){

??????? }

??? }

3)通過subscribe()方法使觀察者訂閱被觀察者

??? Observable.subscribe(Observer observer);//實際調(diào)用的是ObservableCreate.subscribeActual()方法豺妓,具體實現(xiàn)如下

??? protected void subscribeActual(Observer<? super T> observer) {

????????????????? // 1. 創(chuàng)建1個CreateEmitter對象用于發(fā)射事件(封裝成1個Disposable對象)

??????????????? CreateEmitter<T> parent = new CreateEmitter<T>(observer);

??????????????? // 2. 調(diào)用觀察者(Observer)的onSubscribe()

??????????????? observer.onSubscribe(parent);

??????????????? try {

??????????????????? // 3. 調(diào)用source對象的(ObservableOnSubscribe對象)subscribe()

??????????????????? source.subscribe(parent);

??????????????? } catch (Throwable ex) {

??????????????????? Exceptions.throwIfFatal(ex);

??????????????????? parent.onError(ex);

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

??????? }

??? RxJava的作用惜互,與平時使用的異步操作來比的優(yōu)缺點

??? 說說EventBus作用,實現(xiàn)方式琳拭,代替EventBus的方式

??? 從0設(shè)計一款A(yù)pp整體架構(gòu)训堆,如何去做?

??? 說一款你認(rèn)為當(dāng)前比較火的應(yīng)用并設(shè)計(比如:直播APP白嘁,P2P金融坑鱼,小視頻等)

??? 談?wù)剬ava狀態(tài)機(jī)理解

??? Fragment如果在Adapter中使用應(yīng)該如何解耦?

??? Binder機(jī)制及底層實現(xiàn)

??? 對于應(yīng)用更新這塊是如何做的絮缅?(解答:灰度鲁沥,強(qiáng)制更新,分區(qū)域更新)耕魄?

??? 實現(xiàn)一個Json解析器(可以通過正則提高速度)

??? 統(tǒng)計啟動時長,標(biāo)準(zhǔn)

(七)性能優(yōu)化

??? 如何對Android 應(yīng)用進(jìn)行性能分析以及優(yōu)化?

??? ddms 和 traceView

??? 性能優(yōu)化如何分析systrace画恰?

??? 用IDE如何分析內(nèi)存泄漏?

??? Java多線程引發(fā)的性能問題吸奴,怎么解決允扇?

??? 啟動頁白屏及黑屏解決?

??? 啟動太慢怎么解決奄抽?

在冷啟動系統(tǒng)要執(zhí)行三個任務(wù):加載和啟動應(yīng)用程序蔼两;在app啟動后立即顯示一個空白窗體;創(chuàng)建APP進(jìn)程逞度。

應(yīng)用啟動后會執(zhí)行:創(chuàng)建應(yīng)用程序?qū)ο蠖罨粏又骶€程;創(chuàng)建Main Activity档泽;初始化構(gòu)造View俊戳;在屏幕上布局揖赴;執(zhí)行初始化繪制操作;

應(yīng)用啟動抑胎,空白窗口會一直存在直到系統(tǒng)完成了應(yīng)用的首次繪制操作燥滑,此時,系統(tǒng)會替換啟動窗口阿逃,讓用戶能和APP進(jìn)行交互铭拧。

對于熱啟動,如果應(yīng)用的Activity駐留在內(nèi)存中恃锉,應(yīng)用就可避免重復(fù)進(jìn)行對象初始化搀菩。如果系統(tǒng)執(zhí)行了內(nèi)存回收并觸發(fā)GC,如onTrimMemory()破托,熱啟動時對象仍需重建肪跋,這樣系統(tǒng)進(jìn)程也會一直顯示白屏直到應(yīng)用完成Activity的渲染。

測量應(yīng)用啟動時間:1) 可通過logcat中查看Displayed中顯示啟動類耗時; 2) 通過adb shell am start -S -W 包名/啟動類全限定名土砂,-S表示重啟當(dāng)前應(yīng)用州既,命令進(jìn)行檢測啟動app的耗時。3) 使用reportFullyDrawn()方法來測量應(yīng)用啟動到所有資源和視圖層次結(jié)構(gòu)完整顯示之間的所經(jīng)過的時間萝映。

優(yōu)化方法:1)減少view的層級吴叶,減少復(fù)用和布局嵌套使布局扁平化,不要加載對用戶不可見的布局锌俱,如使用ViewStub;

2)將需要在主線程中初始化但可不立即完成的延遲加載晤郑,部分組件放到子線程中初始化。

3)減少Application.onCreate和啟動頁和第一個界面onCreate中方法的耗時操作贸宏。

4)設(shè)置閃屏頁造寝,將閃屏頁設(shè)置為啟動頁的activity窗口背景windowBackground屬性,為啟動屏幕提供一個背景吭练,

??? 怎么保證應(yīng)用啟動不卡頓诫龙?

應(yīng)用卡頓的主要原因有:速度曲線不夠流暢,掉幀鲫咽、觸摸響應(yīng)速度

Android顯示機(jī)制:app->SurfaceFlinger->Display

開發(fā)者選項->GPU呈現(xiàn)模式分析->在屏幕上顯示為條形圖签赃,可以在屏幕上看到顯示每幀繪制花費的時間,有條基準(zhǔn)線是16ms,超過這條基線很可能出現(xiàn)掉幀分尸。如果藍(lán)線很長锦聊,則說明軟件draw太費時,可通過traceview來繼續(xù)分析draw的java代碼箩绍。如果中間紅色部分很長則說明是openGL ES繪制太費時孔庭,用gltrace來分析OpernGL ES調(diào)用過程。用systrace分析,用traceview來看代碼圆到,

??? App啟動崩潰異常捕捉

??? 自定義View注意事項

??? 現(xiàn)在下載速度很慢,試從網(wǎng)絡(luò)協(xié)議的角度分析原因,并優(yōu)化(提示:網(wǎng)絡(luò)的5層都可以涉及)怎抛。

??? Https請求慢的解決辦法(提示:DNS,攜帶數(shù)據(jù)芽淡,直接訪問IP)

??? 如何保持應(yīng)用的穩(wěn)定性

1)需求明確清楚马绝,編碼時明確知道要實現(xiàn)的功能和實現(xiàn)方法,技術(shù)選型等挣菲,對一些庫進(jìn)行封裝再使用富稻。防止代碼冗余、避免多線程導(dǎo)致的問題己单;

2)異常崩潰處理捕獲唉窃,在使用對象前做判空處理等

3)提高編碼質(zhì)量,用lint\findbugs進(jìn)行代碼靜態(tài)分析纹笼;

4)OOM和內(nèi)存泄漏檢測

5)框架測試,兼容性測試苟跪、單元測試廷痘、monkey測試

6)發(fā)布維度,灰度件已,選擇部分渠道進(jìn)行發(fā)布笋额,收集問題;

7)熱更新篷扩。

??? RecyclerView和ListView的性能對比

??? ListView的優(yōu)化

??? RecycleView優(yōu)化

??? View渲染

??? Bitmap如何處理大圖兄猩,如一張30M的大圖,如何預(yù)防OOM

??? java中的四種引用的區(qū)別以及使用場景

??? 強(qiáng)引用置為null鉴未,會不會被回收枢冤?

如果對象沒有被GC Roots引用到,會被GC回收到铜秆,但什么時候回收需根據(jù)JVM的特性什么時候觸發(fā)GC操作淹真。即使調(diào)用了System.gc() JVM也不一定會觸發(fā)GC。

(八)NDK连茧、jni核蘸、Binder、AIDL啸驯、進(jìn)程通信有關(guān)

??? 請介紹一下NDK

??? 什么是NDK庫?

??? jni用過嗎客扎?

??? 如何在jni中注冊native函數(shù),有幾種注冊方式?

??? Java如何調(diào)用c罚斗、c++語言徙鱼?

??? jni如何調(diào)用java層代碼?

1)Java類中要調(diào)用jni方法惰聂,需要在java類中聲明本地方法疆偿,public native void methodName();//本地方法咱筛。還要在類的靜態(tài)代碼塊中導(dǎo)入so庫 static { System.loadLibrary("MyJni");}

2)在C/C++獲取類的對象的方法有兩種:

a)通過c/c++創(chuàng)建java對象,通過對象獲取類杆故,通過類獲取類的構(gòu)造方法的ID迅箩,基于方法ID和類,創(chuàng)建新對象处铛。

??? JNIEXPORT void JNICALL JAVA_nativeMethod(JNIEnv *env, jobject this, jint i) {

??????? jclass clazz = (*env).GetObjectClass(thiz);

??????? jmethodID mid = (*env).GetMethodID(clazz, "<init>","()V");

??????? jobject obj = (*env).NewObject(clazz, mid);

??? }

b) 通過c/c++創(chuàng)建不同類對象饲趋,通過FindClass方法獲取需要的類;通過類獲取類的構(gòu)造方法的ID撤蟆,基于方法ID和類奕塑,創(chuàng)建對象

??? JNIEXPORT void JNICALL JAVA_nativeMethod(JNIEnv *env, jobject this, jint i) {

??????? jclass clazz = (*env).FindClass("com/packagepath/className");

??????? jmethodID mid = (*env).GetMethodID(clazz, "<init>","()V");

??????? jobject obj = (*env).NewObject(clazz, mid);

??? }

調(diào)用java方法跟上面調(diào)用構(gòu)造函數(shù)類似,獲取類的方法ID家肯,基于對象的方法id調(diào)用Java方法

??? JNIEXPORT void JNICALL JAVA_nativeMethod(JNIEnv *env, jobject thiz, jint i) {

??????? jclass clazz = (*env).GetObjectClass(thiz);

??????? m_Object = (*env).NewGlobalRef(thiz);

??????? m_mid = (*env).GetMethodID(clazz, "methodName", "()V");//獲取Java方法的ID

??????? m_fid = (*env).GetFieldID(clazz, "a","I");//獲取Java變量的ID

??????? (*env).SetIntField(m_Object, m_fid, i);

??????? (*env).CallVoidMethod(m_Object, m_mid);

??? }

??? 進(jìn)程間通信的方式龄砰?

??? Binder機(jī)制

??? 簡述IPC?

??? 什么是AIDL讨衣?

??? AIDL解決了什么問題换棚?

??? AIDL如何使用?

??? Android 上的 Inter-Process-Communication 跨進(jìn)程通信時如何工作的反镇?

??? 多進(jìn)程場景遇見過么固蚤?

??? Android進(jìn)程分類?

前臺進(jìn)行(當(dāng)前正在前臺運行的進(jìn)程歹茶,說明用戶當(dāng)前正在與該進(jìn)程交互)夕玩, 滿足以下至少一個條件的叫做 foreground progcess:

? a.有一個Activity在前臺獲得焦點可與用戶互動

? b.有一個 BroadcastReceiver組件正在運行onReceive()方法

? c.有一個Sevice組件正在運行onCreate()/onStart()/onDestory()方法

可見進(jìn)程(可見,但用戶不能直接與之交互)滿足以下條件之一稱為可見進(jìn)程:a.有一個Activity能被用戶看見但是失去焦點(處于onPause()狀態(tài)) b.有一個 Service調(diào)用了startForeground()方法 c.綁定了一個Service惊豺,系統(tǒng)將該Service作為一個特殊的用戶知道的功能使用如自動更換壁紙燎孟,輸入法服務(wù)等。

服務(wù)進(jìn)程(擁有service的進(jìn)程扮叨,一般在后臺為用戶服務(wù)的)缤弦,通過startService()方法開啟的沒有綁定在activity上的Service的進(jìn)程,Service長時間運行 (超過30分鐘以上)會被降級到cached process

后臺進(jìn)程(對用戶作用不大彻磁,缺少該進(jìn)程一般不會影響用戶對系統(tǒng)的體驗)

空進(jìn)程(一般作為緩存機(jī)制服務(wù)的)

??? 進(jìn)程和 Application 的生命周期碍沐?

??? 進(jìn)程調(diào)度

??? 談?wù)剬M(jìn)程共享和線程安全的認(rèn)識

Android進(jìn)程共享可通過共享用戶ID來實現(xiàn),

對于SharedPreferences想實現(xiàn)多進(jìn)程共享需要設(shè)置MODE_MULTI_PROCESS衷蜓,設(shè)置了這個Flag后累提,每次調(diào)用Context.getSharedPreferences時系統(tǒng)會重新從SP

SharedPreferences myPrefs = context.getSharedPreferences(MY_FILE_NAME, Context.MODE_MULTI_PROCESS | Context.MODE_PRIVATE);

??? 談?wù)剬Χ噙M(jìn)程開發(fā)的理解以及多進(jìn)程應(yīng)用場景

??? 什么是協(xié)程?

(九)framework層磁浇、ROM定制斋陪、Ubuntu、Linux之類的問題

??? java虛擬機(jī)的特性

??? 談?wù)剬vm的理解

??? JVM內(nèi)存區(qū)域,開線程影響哪塊內(nèi)存

??? 對Dalvik缔赠、ART虛擬機(jī)有什么了解?

??? Art和Dalvik對比

??? 虛擬機(jī)原理友题,如何自己設(shè)計一個虛擬機(jī)(內(nèi)存管理,類加載,雙親委派)

??? 談?wù)勀銓﹄p親委派模型理解

??? JVM內(nèi)存模型离唬,內(nèi)存區(qū)域

??? 類加載機(jī)制

??? 談?wù)剬lassLoader(類加載器)的理解

??? 談?wù)剬討B(tài)加載(OSGI)的理解

??? 內(nèi)存對象的循環(huán)引用及避免

??? 內(nèi)存回收機(jī)制漾稀、GC回收策略啰脚、GC原理時機(jī)以及GC對象

??? 垃圾回收機(jī)制與調(diào)用System.gc()區(qū)別

System.gc()只是通知垃圾回收器要進(jìn)行垃圾回收操作橄浓,但并沒有立即執(zhí)行垃圾回收。它只是建議JVM安排GC運行,還有可能被拒絕。

??? Ubuntu編譯安卓系統(tǒng)

??? 系統(tǒng)啟動流程是什么三妈?(提示:Zygote進(jìn)程 –> SystemServer進(jìn)程 –> 各種系統(tǒng)服務(wù) –> 應(yīng)用進(jìn)程)

??? 大體說清一個應(yīng)用程序安裝到手機(jī)上時發(fā)生了什么

??? 簡述Activity啟動全部過程

1)Activity.startActivity-->startActivityForResult()

2)-->Instrumentation.execStartActivity()-->execStartActivity()

3)ActivityManager.getService().startActivity()通過Binder到ActivityManagerService.startActivity()

4)-->ActivityStarter.startActivityMayWait()-->startActivityLocked()-->startActivityUnchecked()

5)--ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()-->ApplicationThread$scheduleLaunchActivity

6)ApplicationThread.schedulelaunchActivity()通過ActivityThread.sendMessage,再處理消息心肪,進(jìn)入handleLaunchActivity

-->Instrumentation$newActivity創(chuàng)建Activity的實例,使用類加載器創(chuàng)建Activity對象桦沉。

-->makeApplication創(chuàng)建Application對象,調(diào)用它的Application.onCreate()方法

Instrumentation這個類就是完成對Application和Activity初始化和生命周期的工具類钞速。

??? App啟動流程,從點擊桌面開始

1)點擊桌面App圖標(biāo),Launcher進(jìn)程采用Binder IPC向system_server進(jìn)程發(fā)送startActivity()

2)system_server進(jìn)程向Zygote發(fā)送創(chuàng)建進(jìn)程的請求(AMS中通過startActivity()方法玷过,調(diào)用startProcessLocked()函數(shù))谤狡,Zygote通過socket通信的方式讓Zygote進(jìn)程 fork一個新進(jìn)程出來作為App進(jìn)程;

3)App進(jìn)程通過Binder IPC向system_server進(jìn)程發(fā)起attachApplication請求(ActivityThread的main()函數(shù)里會創(chuàng)建Application,還調(diào)用ActivityStackSupervisor.attachApplicationLocked)蝉绷;

4)system_server進(jìn)程收到請求后,進(jìn)行一系列準(zhǔn)備工作垂攘,再通過binder IPC向APP進(jìn)程發(fā)送scheduleLaunchActivity請求维雇;

5)App進(jìn)程的binder線程(ApplicationThread)收到請求后,通過handler向主線程發(fā)送LAUNCHER_ACTIVITY消息晒他;

6)主線程收到Message消息后吱型,通過反射機(jī)制創(chuàng)建出Activity并回調(diào)Activity.onCreate()等方法;

7)App正式啟動陨仅,開始進(jìn)入Activity的生命周期津滞。

??? 邏輯地址與物理地址,為什么使用邏輯地址灼伤?

??? Android為每個應(yīng)用程序分配的內(nèi)存大小是多少触徐?

根據(jù)應(yīng)用實際使用情況分配,初始給進(jìn)程分配為8M狐赡,應(yīng)用最大可分配的可能是64M\128M\256M等

??? Android中進(jìn)程內(nèi)存的分配撞鹉,能不能自己分配定額內(nèi)存?

進(jìn)程內(nèi)存分配跟手機(jī)配置有關(guān)颖侄,不同手機(jī)可能不一樣鸟雏,有64M\128M\256M等,heapgrowthlimit是一個普通應(yīng)用的內(nèi)存限制览祖,可通過ActivityManager.getLargeMemoryClass()獲得孝鹊,在mainfest中設(shè)置了largeHeap=true后,可以使應(yīng)用可用內(nèi)存增大到原來兩倍展蒂。并不能自己定額分配內(nèi)存又活,android系統(tǒng)是根據(jù)應(yīng)用所需要內(nèi)存大小苔咪,先分配初始大小heapstartsize,當(dāng)應(yīng)用申請更多內(nèi)存皇钞,系統(tǒng)會再進(jìn)行分配悼泌,但不得超過最大內(nèi)存,超過了會報OOM夹界。

??? 進(jìn)程惫堇铮活的方式

1)模擬前臺進(jìn)程,startForeground()將當(dāng)前進(jìn)程偽裝成前臺進(jìn)程可柿,將進(jìn)程優(yōu)先級提高到最高鸠踪,現(xiàn)在前臺進(jìn)程會顯示在通知欄中,取消不掉复斥。

2)JobScheduler機(jī)制喚醒营密,系統(tǒng)會根據(jù)自己實現(xiàn)定時去調(diào)用改接口傳遞進(jìn)程去實現(xiàn)一些操作,且這個接口被強(qiáng)制停止后仍能正常啟動目锭。在調(diào)用JobSchedule.schedule()來啟動任務(wù)评汰。

3)實現(xiàn)Service類時,將onStartCommand()返回值設(shè)置為START_STICKY痢虹,利用系統(tǒng)機(jī)制在service掛掉后自動拉活被去,但這種方式只適合原生系統(tǒng),像小米奖唯、華為等定制化比較高的第三方廠商惨缆,這些都限制了。

4)一像素的Activity丰捷,

5)應(yīng)用之間相互喚醒坯墨。

??? 如何保證一個后臺服務(wù)不被殺死?(相同問題:如何保證service在后臺不被kill病往?)比較省電的方式是什么捣染?

??? App中喚醒其他進(jìn)程的實現(xiàn)方式

1)啟動其他進(jìn)程的Activity\Service或是發(fā)送一條廣播給相應(yīng)的應(yīng)用(該應(yīng)用得靜態(tài)注冊此廣播)

OOM定位與分析,如何定位哪塊原因?qū)е聭?yīng)用最終發(fā)生OOM停巷?

OOM發(fā)生后液斜,可以用Android Studio自帶的Android Monitor dump出HPROF文件,再用SDK中hprof-conv工具轉(zhuǎn)換為標(biāo)準(zhǔn)的Java堆轉(zhuǎn)儲文件格式叠穆,再用MAT繼續(xù)分析。切換到histogram視圖臼膏,按shadow heap降序排序硼被,對實例對象占用內(nèi)存大小排序,再查看實例到GC ROOT的路徑渗磅。

一般可能導(dǎo)致的如圖片:直接加載超大尺寸圖片(對圖片尺寸縮放預(yù)處理后再加載)嚷硫、圖片加載后未及時釋放(利用LRU機(jī)制保證圖片個數(shù)和占用內(nèi)存)检访;在頁面中,加載非常多的圖片(避免同時加載大量圖片)

JNI層的crash如何捕獲仔掸?

通過ndk安裝包中的addr2line objdump? ndk-stack工具進(jìn)行分析crash脆贵,ndk針對不同的CPU架構(gòu)實現(xiàn)了多套相同的工具,在選擇add2line objdump時要根據(jù)目標(biāo)機(jī)器CPU架構(gòu)來選擇起暮。

一般JNI發(fā)生異常卖氨,會出現(xiàn)一個Fatal signal信號量,大概知道是哪個函數(shù)引起的负懦,再看下面的backtrace日志眠菇,backtrace是JNI調(diào)用堆棧信息厘熟,以“#兩位數(shù)字 pc”開頭,找到對應(yīng)的函數(shù),再用addr2line進(jìn)行定位出錯的位置断傲。addr2line -C -f -e ./obj/armeabi/xxx.so 000eea70

使用ndk-stack協(xié)助我們獲取底層崩潰的堆棧信息,adb logcat | ndk-stack -sym ./obj/armeabi/xxx.so

應(yīng)用卡頓定位

1)使用UI線程的Looper打印日志

Android主線程更新UI趾徽,如果1S鐘刷新少于60次侧巨,即FPS小于60,一幀加載超過16.67ms的話躯枢,用戶就會產(chǎn)生卡頓的感覺则吟。Android使用消息機(jī)制進(jìn)行UI更新,UI線程中有個Looper闺金,其loop方法會不斷提取message逾滥,調(diào)用其綁定的Handler在UI線程執(zhí)行。如果handler.dispatchMessage方法中有耗時操作败匹,就會發(fā)生卡頓寨昙。如果有卡頓,就打印出UI線程的堆棧信息掀亩。

優(yōu)點:用戶使用app就可以監(jiān)控卡頓情況舔哪,但因需另開子線程獲取堆棧信息,會消耗系統(tǒng)資源槽棍。

2)使用Choreographer.FrameCallback監(jiān)控卡頓

Android系統(tǒng)每16ms會發(fā)出SYNC信息捉蚤,通知界面重繪、渲染炼七,每一次同步的周期為16.6ms缆巧,代表一幀的刷新頻率可以在兩次回調(diào)時間周期來判斷是否發(fā)生卡頓。(Android4.1以上才支持)豌拙∩滦可以通過Choreographer.FrameCallback回調(diào)doFrame(long)函數(shù),如果兩次doFrame之間間隔大于16.67ms說明發(fā)生了卡頓按傅。這種方法從app層面來監(jiān)控卡頓捉超,同時可實時計算幀率和掉幀數(shù)胧卤,實時監(jiān)測APP頁面的幀率數(shù)據(jù),一旦發(fā)現(xiàn)幀率過低拼岳,可自動保存現(xiàn)場堆棧信息枝誊。

卡頓監(jiān)控系統(tǒng)處理流程:開發(fā)修復(fù)-》用戶上報(后臺配置下灰度0.2%的用戶量進(jìn)行卡頓監(jiān)控和上報,每個用戶一天上報一次惜纸,上報后刪除文件不影響存儲空間)-》后臺解析(過濾叶撒、去重、分類堪簿、反解堆棧痊乾、入庫)-》平臺展示-》自動提單

Http2.0有關(guān)多路復(fù)用:

多路復(fù)用原理:HTTP2流和多路復(fù)用?? HTTP2.0原理詳細(xì)解析

原理是二進(jìn)制分幀層+流實現(xiàn)了多路復(fù)用,OKHttp是怎么支持的呢椭更,那就是讀幀哪审,讀流,Okhttp對http2的支持簡單分析

ViewStub是怎么實現(xiàn)延時加載的虑瀑?

ViewStub是一個不可見湿滓、大小為0的View。具體體現(xiàn)在ViewStub的構(gòu)造函數(shù)中會進(jìn)行設(shè)置setVisibility(GONE)設(shè)置控件不可見舌狗,同時會設(shè)置setWillNotDraw(true),即本View不會調(diào)用onDraw()方法繪制內(nèi)容叽奥。在它的onMeasure函數(shù)中會調(diào)用setMeasureDimenssion(0, 0)即不會測量視圖,直接設(shè)置一個大小為0的View.

對于ViewStub.inflate()機(jī)制是:1)調(diào)用LayoutInflate.flate(mLayoutResource, parent, false)來加載ViewStub中android:layout設(shè)置的布局view(最后一個參數(shù)false是代表attachToRoot設(shè)置成false痛侍,說明忽略android:layout中布局根節(jié)點的layoutParams參數(shù))朝氓;2)從父視圖中獲取當(dāng)前ViewStub在父視圖中位置(在加載父視圖時會用一個占位符來代表ViewStub);3)將當(dāng)前ViewStub從parent中移除主届;4)將android:layout中的布局view add到父視圖中赵哲,如果StubView中設(shè)置了layoutParams屬性就會用ViewStub中設(shè)置的。

應(yīng)用場景:如網(wǎng)絡(luò)加載失敗頁面君丁,評論區(qū)域內(nèi)的listView(當(dāng)沒有評論或是請求失敗的時候不加載)

加載方式:findViewById(R.id.stubViewId).setVisibility(View.VISIBLE);或是((ViewStub)findViewById(R.id.StubViewId)).inflate();其實設(shè)置Visibility最終也是調(diào)用inflate來加載布局的枫夺。

如果ViewStub標(biāo)簽下寫上width/height,在ViewStub相應(yīng)的layout xml文件中也進(jìn)行了寬高定義绘闷,會以誰為準(zhǔn)橡庞?

其實上面也分析過了,會以ViewStub中設(shè)置的layoutParams為準(zhǔn)印蔗。

ViewStub可不可以加載多次呢扒最?

不能,上面也分析過了华嘹,ViewStub調(diào)用inflate()方法后扼倘,會把自己從父視圖中移除掉,并把自身所包含的內(nèi)容添加到父視圖中,再重新加載再菊,找不到在父視圖了,就會拋出ViewStub must have a non-null ViewGroup viewparent颜曾。

merge標(biāo)簽

merge一般可以和include/ViewStub結(jié)合使用纠拔,當(dāng)include/ViewStub從外部導(dǎo)入xml結(jié)構(gòu)時,可以將被導(dǎo)入的xml用merge作為根節(jié)點表示泛豪,當(dāng)被加載到父布局中可以將它們?nèi)诤系礁讣壗Y(jié)構(gòu)中稠诲,而不會出現(xiàn)冗余的節(jié)點。因為它是直接將其中的子元素添加到merge標(biāo)簽的parent中诡曙,這樣就保證不會引入額外的層級了臀叙。

注意:1)<merge />只可以作為xml layout的根節(jié)點;2)當(dāng)需要擴(kuò)展的xml layout本身的根節(jié)點也是merge時价卤,需要將被導(dǎo)入的xml layout置于ViewGroup中劝萤,且設(shè)置attachToRoot為true。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慎璧,一起剝皮案震驚了整個濱河市床嫌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胸私,老刑警劉巖厌处,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異岁疼,居然都是意外死亡阔涉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門捷绒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑰排,“玉大人,你說我怎么就攤上這事疙驾⌒谆铮” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵它碎,是天一觀的道長函荣。 經(jīng)常有香客問我,道長扳肛,這世上最難降的妖魔是什么傻挂? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮挖息,結(jié)果婚禮上金拒,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好绪抛,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布资铡。 她就那樣靜靜地躺著,像睡著了一般幢码。 火紅的嫁衣襯著肌膚如雪笤休。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天症副,我揣著相機(jī)與錄音店雅,去河邊找鬼。 笑死贞铣,一個胖子當(dāng)著我的面吹牛闹啦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辕坝,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窍奋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了圣勒?” 一聲冷哼從身側(cè)響起费变,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎圣贸,沒想到半個月后挚歧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡吁峻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年滑负,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片用含。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡矮慕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出啄骇,到底是詐尸還是另有隱情痴鳄,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布缸夹,位于F島的核電站痪寻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏虽惭。R本人自食惡果不足惜橡类,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芽唇。 院中可真熱鬧顾画,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至庶诡,卻和暖如春虾标,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灌砖。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留傀蚌,地道東北人基显。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像善炫,于是被迫代替她去往敵國和親撩幽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353

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