android面試筆試總結(jié)(android篇)

Activity中的幾種啟動模式

activity的幾種啟動模式是android中郴崆埃考的知識點,一般會考察有哪幾種啟動模式,以及每種啟動模式在什么場景下使用:

standard:這個是android默認(rèn)的Activity啟動模式疚颊,每啟動一個Activity都會被實例化一個Activity漏隐,并且新創(chuàng)建的Activity在堆棧中會在棧頂喧半。

singleTop:如果當(dāng)前要啟動的Activity就是在棧頂?shù)奈恢茫敲创藭r就會復(fù)用該Activity青责,并且不會重走onCreate方法挺据,會直接它的onNewIntent方法,如果不在棧頂脖隶,就跟standard一樣的扁耐。如果當(dāng)前activity已經(jīng)在前臺顯示著,突然來了一條推送消息浩村,此時不想讓接收推送的消息的activity再次創(chuàng)建做葵,那么此時正好可以用該啟動模式,如果之前activity棧中是A-->B-->C如果點擊了推動的消息還是A-->B--C心墅,不過此時C是不會再次創(chuàng)建的酿矢,而是調(diào)用C的onNewIntent。而如果現(xiàn)在activity中棧是A-->C-->B怎燥,再次打開推送的消息瘫筐,此時跟正常的啟動C就沒啥區(qū)別了,當(dāng)前棧中就是A-->C-->B-->C了铐姚。

singleTask:該種情況下就比singleTop厲害了策肝,不管在不在棧頂肛捍,在Activity的堆棧中永遠(yuǎn)保持一個。這種啟動模式相對于singleTop而言是更加直接之众,比如之前activity棧中有A-->B-->C---D拙毫,再次打開了B的時候,在B上面的activity都會從activity棧中被移除棺禾。下面的acitivity還是不用管缀蹄,所以此時棧中是A-->B,一般項目中主頁面用到該啟動模式膘婶。

singleInstance:該種情況就用得比較少了缺前,主要是指在該activity永遠(yuǎn)只在一個單獨的棧中。一旦該模式的activity的實例已經(jīng)存在于某個棧中悬襟,任何應(yīng)用在激活該activity時都會重用該棧中的實例衅码,解決了多個task共享一個activity。其余的基本和上面的singleTask保持一致脊岳。

上面的各種啟動模式主要是通過配置清單文件逝段,常見還有在代碼中設(shè)置flag也能實現(xiàn)上面的功能:

FLAG_ACTIVITY_CLEAR_TOP:這種啟動的話,只能單純地清空棧上面的acivity逸绎,而自己會重新被創(chuàng)建一次惹恃,如果當(dāng)前棧中有A-->B-->C這幾種情況,重新打開B之后棺牧,此時棧會變成了A-->B巫糙,但是此時B會被重新創(chuàng)建,不會走B的onNewIntent方法颊乘。這就是單獨使用FLAG_ACTIVITY_CLEAR_TOP的用處参淹,能清空棧上面的activity,但是自己會重新創(chuàng)建乏悄。
如果在上面的基礎(chǔ)上再加上FLAG_ACTIVITY_SINGLE_TOP此時就不重新創(chuàng)建B了浙值,也就直接走B的onNewIntent。它兩者結(jié)合著使用就相當(dāng)于上面的singleTask模式檩小。
如果只是單獨的使用FLAG_ACTIVITY_SINGLE_TOP跟上面的singleTop就沒啥區(qū)別了开呐。

FLAG_ACTIVITY_CLEAR_TOP+FLAG_ACTIVITY_SINGLE_TOP=singleTask,此時要打開的activity不會被重建,只是走onNewIntent方法规求。

FLAG_ACTIVITY_SINGLE_TOP=singleTop

FLAG_ACTIVITY_NEW_TASK

  • 在相同taskAffinity情況下:啟動activity是沒有任何作用的筐付。

  • 在不同taskAffinity情況下:
    如果啟動不同棧中的activity已經(jīng)存在了某一個棧中的activity,那么此時是啟動不了該activity的阻肿,因為棧中已經(jīng)存在了該activity瓦戚;如果棧中不存在該要啟動的activity,那么會啟動該acvitity丛塌,并且將該activity放入該棧中较解。

FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP一起使用畜疾,并且要啟動的activity的taskAffinity和當(dāng)前activity的taskAffinity不一樣才會和singleTask一樣的效果,因為要啟動的activity和原先的activity不在同一個taskAffinity中印衔,所以能啟動該activity啡捶,這個地方有點繞,寫個簡單的公式:

  • FLAG_ACTIVITY_NEW_TASK如果啟動同一個不同taskAffinity的activity才會有效果奸焙。
  • FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP如果一起使用要開啟的activity和現(xiàn)在的activity處于同一個taskAffinity届慈,那么效果還是跟沒加FLAG_ACTIVITY_NEW_TASK是一樣的效果。
  • FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP啟動和現(xiàn)在的activity不是同一個taskAffinity才會和singleTask一樣的效果忿偷。

FLAG_ACTIVITY_CLEAR_TASK

  • 在相同taskAffinity情況下:和FLAG_ACTIVITY_NEW_TASK一起使用,啟動activity是沒有任何作用的臊泌。
  • 在不同taskAffinity情況下:和FLAG_ACTIVITY_NEW_TASK一起使用鲤桥,如果要啟動的activity不存在棧中,那么啟動該acitivity渠概,并且將該activity放入該棧中茶凳,如果該activity已經(jīng)存在于該棧中,那么會把當(dāng)前棧中的activity先移除掉播揪,然后再將該activity放入新的棧中贮喧。

FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_SINGLE_TOP用在當(dāng)app正在運行點擊push消息進到某個activity中的時候,如果當(dāng)前處于該activity猪狈,此時會觸發(fā)activity的onNewIntent箱沦。

FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_CLEAR_TOP用在app沒在運行中,啟動主頁的activity雇庙,然后在相應(yīng)的activity中做相應(yīng)的activity跳轉(zhuǎn)谓形。

android消息機制

消息機制指Handler、Looper疆前、MessageQueue寒跳、Message之間如何工作的。

  • handler是用來處理消息和接收消息的中間者竹椒,handler的創(chuàng)建會伴隨著handler中產(chǎn)生looper和MessageQueue童太,handler依賴于looper,looper依賴于MessageQueue胸完,所以在子線程中使用handler拋出異常是因為子線程中沒有初始化looper對象书释,而主線程中l(wèi)ooper是在ActivityThread中已經(jīng)初始化過了,所以能直接在主線程中能拿到Handler舶吗。

  • Looper是用來輪詢消息征冷,說白了就是通過loop方法實現(xiàn)死循環(huán),有消息的時候誓琼,通過MessageQueue.next方法取出message检激,沒有消息的時候肴捉,線程處于阻塞的狀態(tài)。在有消息的時候獲取到消息叔收,將消息交給了handler齿穗,handler會根據(jù)消息中有沒有callback,如果有callback會直接callback饺律,否則通過handleMessage處理窃页。

  • MessageQueue是一個單鏈表結(jié)構(gòu)來存儲Message,每次通過next方法取出Message消息后复濒,取完之后將message.next給當(dāng)前的message脖卖,再將message.next=null,實際上就是移除當(dāng)前的message巧颈。但是在looper里面每次在next取出message后畦木,放到了message的sPool里面,緩存起來方便使用砸泛。

  • Message就沒什么好說的十籍,主要存儲平常經(jīng)常用的obj和what信息,以及我們不用關(guān)心的target和callback等唇礁。

這里會問到勾栗,一個線程會有幾個Looper,幾個Handler盏筐,以及Looper會存在線程哪里围俘?

一個線程一個Looper,可以有多個Handler机断,Looper會存在線程的ThreadLocal對象里楷拳,該對象是線程的緩存區(qū)

ThreadLocal:它是和線程一一對應(yīng)的,從Thread類可以看出來吏奸,ThreadLocal是作為Thread變量來使用欢揖。ThreadLocal只是ThreadLocalMap的一個包裝類,實現(xiàn)了get和set方法奋蔚,而ThreadLocalMap實際是一個由Entry內(nèi)部類組成的數(shù)組她混,Entry是繼承自弱應(yīng)用,弱引用里面放的就是ThreadLocal當(dāng)前對象泊碑,Entry的value存的是當(dāng)前線程要存儲的對象坤按,value作為Entry的成員變量。
ThreadLocal經(jīng)常會問到內(nèi)存泄漏的問題馒过,從上面分析可以發(fā)現(xiàn)ThreadLocalMap里面的Entry對象存儲的ThreadLocal弱引用臭脓,而value直接作為Entry的強引用,因此在用到了ThreadLocal的地方腹忽,防止內(nèi)存泄漏来累,手動調(diào)用remove方法砚作。

IntentService

IntentService是google在原生的Service基礎(chǔ)上通過創(chuàng)建子線程的Service。也就是說IntentService是專門為android開發(fā)者提供的能在service內(nèi)部實現(xiàn)耗時操作的service嘹锁。我們可以通過重寫onHandleIntent方法實現(xiàn)耗時操作的回調(diào)處理葫录,而且IntentService在耗時操作完成后,會主動銷毀自己领猾,IntentService可以通過多次啟動來完成多個任務(wù)米同,而IntentService只會被創(chuàng)建一次,每次啟動的時候只會觸發(fā)onStart方法摔竿。內(nèi)部是實現(xiàn)了Handler異步處理耗時操作的過程面粮,一般多用在Service中需要處理耗時操作的功能。

提問:為什么IntentService中能實現(xiàn)耗時操作?

  • 在onCreate中继低,通過HandlerThread來開啟一條線程但金,而HandlerThread線程中會跟我們平常用的Handler不太一樣,在run方法中創(chuàng)建了looper對象郁季,所以HandlerThread能讓IntentService在子線程中使用handler達(dá)到耗時操作。

HandlerThread

HandlerThread本身也是Thread钱磅,只是在Thread基礎(chǔ)上封裝上了Handler的載體梦裂,并且在run方法中創(chuàng)建了looper對象,這也是為什么在IntentService中能在HandlerThread中直接用handler的原因盖淡。而我們知道一個線程是可以有多個handler年柠,所以用HandlerThread更加方便我們不用關(guān)心Handler的創(chuàng)建,一般用在多線程中直接處理任務(wù)褪迟。

事件分發(fā)

事件分發(fā)主要分三塊:分發(fā)冗恨、攔截、消費味赃;
當(dāng)我們觸摸到屏幕的時候掀抹,默認(rèn)會先走Activity的分發(fā),接著走ViewGroup的分發(fā)心俗,然后到ViewGroup的攔截傲武,后面再到View的分發(fā)事件,最后會傳到View的消費事件城榛,如果View不消費揪利,緊接著回傳到ViewGroup的消費事件,如果ViewGroup也不消費狠持,最后回到View的消費事件疟位。整個事件分發(fā)構(gòu)成了一個u型結(jié)構(gòu),下面總結(jié)了分發(fā)的細(xì)節(jié)流程:

  • 在action_down的時候喘垂,首先去判斷viewgroup的onInterceptTouchEvent是不是攔截了甜刻,如果攔截的話intercepted=true绍撞,就會走handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS);方法,此處傳的child是null罢吃,因此直接走super.dispatchTouchEvent方法楚午,不走child的dispatchTouchEvent方法
  • 如果onInterceptTouchEvent不攔截,那么在action_down的時候尿招,去獲取child.dispatchTouchEvent方法矾柜,如果返回true,那么mFirstTouchTargetnewTouchTarget都不為空就谜,因此在action_move和action_up的時候會走child的dispatchTouchEventontouchEvent方法
  • 如果child的dispatchTouchEvent方法返回false或者child的ontouchEvent返回false怪蔑,mFirstTouchTargetnewTouchTarget都為空,因此在action_moveaction_up的時候不走child的dispatchTouchEventontouchEvent方法丧荐。
  • 如果點擊的是viewgroup缆瓣,那么viewgroup的onInterceptTouchEvent的action_move和action_up都不會被執(zhí)行。

這里會問到事件沖突的問題虹统?

事件遵循一個原則弓坞,就是看他有沒有事件消費。比如一個LinearLayout里面有一個Button车荔,點擊LinearLayout會觸發(fā)到Button嗎渡冻,這里就看LinearLayout有沒有設(shè)置點擊事件,如果有就不會傳遞到Button忧便,如果沒有就會傳遞給Button族吻。

view事件分發(fā)流程圖

android性能優(yōu)化、內(nèi)存優(yōu)化

性能優(yōu)化:可以從界面珠增、apk瘦身超歌、混淆說起,dex分包處理蒂教,插件化動態(tài)加載模塊巍举,開屏冷啟動說起

界面優(yōu)化:多可以使用include、merge凝垛、ViewStub禀综、約束布局來做起,include可以提取公共的布局苔严,merge可以減少布局層次定枷、ViewStub是使用的時候才去創(chuàng)建View,減少空間的占用届氢、約束布局一來可以減少布局的層次欠窒、二來可以提高開發(fā)的效率,在自定義view中注意view繪制過程不要做初始化的操作,一般放到view的初始化的方法里面岖妄。

apk瘦身:可以用android studio的lint檢測工具檢測資源文件等

混淆:可以起到文件大小減少的作用型将,這個在實踐中可以嘗試,混淆后可以反編譯看看apk包的內(nèi)容

dex分包:主要是apk包的結(jié)構(gòu)發(fā)生了變化荐虐,如果dex包的方法數(shù)超過了最大數(shù)七兜,需要進行分包處理

插件化:主要用到了java中動態(tài)代理模式和反射的思想,利用android的activity啟動流程福扬,通過動態(tài)代理模式動態(tài)加載我們需要插件化的activity

開屏冷啟動:開屏冷啟動主要針對MultiDex啟動做優(yōu)化腕铸,在5.0之前對dex分包是不做處理的,所以要兼容到低版本的時候需要使用MultiDex.install做兼容铛碑。而MutiDex.install將apk中的dex包獲取到狠裹,然后又壓縮成對應(yīng)的zip文件,將dex文件通過反射轉(zhuǎn)換成DexFile對象汽烦、反射替換數(shù)組涛菠。所以我們能做的優(yōu)化可以通過判斷如果jvm不支持dex分包處理,通過MutiDex.install做處理撇吞,通過監(jiān)聽MutiDex.install開啟一個監(jiān)聽MutiDex.install的進程activity俗冻。等到MutiDex.install處理完成后,再來處理正常的邏輯牍颈。

內(nèi)存優(yōu)化

內(nèi)存優(yōu)化通常指的內(nèi)存溢出言疗,主要涉及到的問題還是該釋放的資源,沒有及時讓GC處理器回收颂砸,通常主要表現(xiàn)是動畫、上下文對象死姚、EventBus人乓、AsycTask、Handler都毒、單例Bitmap都會影響色罚,通常要做的是釋放他們未終止的動作,釋放鎖定的上下文對象账劲。

在實際項目有mvp架構(gòu)的時候戳护,需要注意內(nèi)存泄漏的問題,p層如果長期持有v層的實例瀑焦,導(dǎo)致v層的對象難以回收腌且,而v層一般是activity或fragment作為抽象,因此需要在p層使用v層的弱應(yīng)用或是在p層中實現(xiàn)v層的銷毀方法榛瓮,處理銷毀的邏輯铺董。

View的繪制

activity界面顯示流程:activity啟動后,不會立馬去顯示界面上的view禀晓,而是等到onResume的時候才會真正顯示view的時機精续,首先會觸發(fā)windowManager.addView方法坝锰,在該方法中觸發(fā)代理對象WindowManagerGlobal的addView方法,代理對象的addView方法中創(chuàng)建了viewRootImpl重付,將setContentView中創(chuàng)建的decorView通過viewRootImpl的setView方法放到了viewRootImpl中顷级,最終經(jīng)過viewRootImpl一系列的方法最終調(diào)用performTraversals方法。

view的繪制:主要指view的onMeasure确垫、onLayout弓颈、onDraw幾個方法,其實要了解幾個方法森爽,需要追溯到android中本身界面的結(jié)構(gòu)恨豁,首先整體是一個PhoneWindow的對象,然后是一個DecorView爬迟,DecorView里面包括一個ViewStub的ToolBar橘蜜,然后下面是一個FramLayout,也就是我們經(jīng)常在Activity中setContentView中的content內(nèi)容付呕。說完了android界面的結(jié)構(gòu)计福,下面就是說下如何繪制的,繪制首先是觸發(fā)到DecorView的onMeasure方法徽职,它的測量規(guī)則包含了手機屏的寬高象颖,并且測量模式是MeasureSpec.EXACTLY。所以這里明白了DecorView(FrameLayout)的測量參數(shù)是什么意思了姆钉,緊接著就是測量它下面的ViewGroup了说订,其中ViewGroup里面有個measureChild方法去測量孩子,這里會問到幾種父布局的測量模式和子View的測量模式組合:

ViewGroup的測量mode MeasureSpec.EXACTLY MeasureSpec.AT_MOST MeasureSpec.UNSPECIFIED
childDimension>0 size=childDimension;mode=EXACTLY size= childDimension;mode=EXACTLY size= childDimension;mode=EXACTLY
childDimension == LayoutParams.MATCH_PARENT size=Viewgroup的size;mode=EXACTLY size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=UNSPECIFIED
childDimension == LayoutParams.WRAP_CONTENT size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=AT_MOST size=Viewgroup的size;mode=UNSPECIFIED

測量處理完了之后潮瓶,緊接著就是View的onLayout陶冷,其中onLayout的作用是給View固定好位置,該方法傳進來的幾個參數(shù)是相對于自己的parent的位置毯辅,左上角是(0,0)的坐標(biāo)埂伦。最后就是我們的onDraw,該方法是我們需要在畫布上畫東西的方法思恐,一般包括畫背景沾谜、畫圖層等等。

Eventbus原理

EventBus是一款在android開發(fā)中使用的發(fā)布/訂閱事件的總線框架胀莹,基于觀察者模式基跑,將事件的接收者和發(fā)送者分開,基本包括了如下幾個步驟:

注冊事件的訂閱方法:該步驟主要是找到訂閱者下面有哪些方法需要被訂閱
訂閱操作:將需要被訂閱的方法放到類似HashMap的數(shù)據(jù)結(jié)構(gòu)中存儲起來描焰,方便后面發(fā)送事件和取消注冊等資源的釋放的時候使用
發(fā)送事件:該步驟首先遍歷事件隊列涩僻,然后從隊列中取出事件,并且將事件從隊列中移除,拿到事件后逆日,判斷事件處于的什么線程嵌巷,如果是非UI線程,則需要Handler去處理室抽,如果是的話搪哪,則直接通過反射調(diào)用被觀察的方法。
反注冊:該步驟就沒什么好說的坪圾,主要是上面存儲到HashMap中的被訂閱的方法的移除晓折,釋放在內(nèi)存中的資源。

Rxjava的操作符有哪些兽泄,說說他們的作用

just:將同種數(shù)據(jù)源組合放到被觀察者上面

from:將類似數(shù)組漓概、集合的數(shù)據(jù)源放到被觀察者上面

map:將一種數(shù)據(jù)源,轉(zhuǎn)化成另外一種

flatmap:將一種數(shù)據(jù)源病梢,轉(zhuǎn)化成另外一種數(shù)據(jù)胃珍,并且被轉(zhuǎn)化的數(shù)據(jù)是亂序排列的

concatmap:將一種數(shù)據(jù)源,轉(zhuǎn)化成另外一種數(shù)據(jù)蜓陌,并且被轉(zhuǎn)化的數(shù)據(jù)是按照先前的數(shù)據(jù)源順序排序的

toList:將數(shù)組的形式轉(zhuǎn)化成List集合

subscribeOn:設(shè)置Observable的call方法所在的線程觅彰,也就是數(shù)據(jù)來源的線程

observeOn:設(shè)置subscribe的call方法所在的線程,也就是數(shù)據(jù)處理的線程

filter:在被觀察者的數(shù)據(jù)層過濾數(shù)據(jù)

onErrorResumeNext:出錯的時候钮热,可以指定出錯的時候的被觀察者

retryWhen:出錯的時候填抬,重新走一遍被訂閱的過程

concat:合并相同類型的被觀察者到一個被觀察者身上,有點類似集合隧期、數(shù)組拼接數(shù)據(jù)飒责。

zip:處理多種不同結(jié)果集的數(shù)據(jù)發(fā)射,一般用得多的地方是多個網(wǎng)絡(luò)請求組合然后統(tǒng)一處理業(yè)務(wù)邏輯仆潮。
還有很多操作符就自己去看宏蛉,這些操作符已經(jīng)夠面試用的了。

線程鎖 鎖方法和類對象啥的有啥區(qū)別

線程鎖鎖方法:是需要等到該線程用完了該方法才能釋放同步鎖
線程鎖鎖類對象:是需要等到該線程用完了該類對象才能釋放同步鎖
區(qū)別:是鎖方法的區(qū)域要小 鎖類對象包括了該類的所有屬性

AsyncTask原理

AsyncTask主要是對android中java的線程池的封裝鸵闪,該類中默認(rèn)開啟了兩個線程池,一個線程池負(fù)責(zé)任務(wù)的排隊處理暑诸,保證任務(wù)被單個處理蚌讼,另外一個線程池用來專門處理任務(wù),最后任務(wù)處理完了个榕,交給Handler發(fā)送消息到主線程篡石,然后Handler處理線程,交給了onPostExecute方法西采。

說說MVP和MVVM的特點

MVP:主要是分離了M層和V層的代碼凰萨,通過P層來建立他們的關(guān)聯(lián),實現(xiàn)M層和V層的解耦。缺點就是每增加一個功能胖眷,需要增加相應(yīng)的接口回調(diào)武通。沒辦法,MVP的核心就是通過接口實現(xiàn)隔離珊搀,將相關(guān)的業(yè)務(wù)層交給了P層冶忱。

如果要細(xì)說mvp需要注意幾點:

  • p層的邏輯處理單一的功能,不要融合一個模塊下的增刪改查的整個功能境析。
  • 由于p層持有了v層的引用囚枪,通常在p層使用弱引用來持有view層實例,在p層銷毀的時候需要將v層的引用銷毀掉劳淆。
  • 契合類指的p層和v層的接口類放在一個contract接口類中链沼,契合類方便管理業(yè)務(wù)層的功能,將單個功能放到一個contract契合類中沛鸵。比如我們有一個添加書架的功能:
public interface AddBookShelfContract {
    interface View extends BaseContract.BaseView {
        void addBookShelfSuccess(BookShelfItem... bookShelfItem);

        void addBookShelfFail();

        void alreadyBookShelf(BookShelfItem bookShelfItem);
    }

    interface Presenter extends BaseContract.BasePresenter<View> {
        void addBookShelf(String tokenId, BookShelfItem... bookShelfItem);
    }
}

MVVM:主要是用到了觀察者模式括勺,通過數(shù)據(jù)的改變來通知相應(yīng)的View改變的過程。M層和上面的MVP中的M層是一樣的谒臼,都是網(wǎng)絡(luò)請求+數(shù)據(jù)緩存來實現(xiàn)該層的朝刊,里面的雙V,一個指的ViewModel實現(xiàn)的蜈缤,另外一個AndroidDataBinding實現(xiàn)V層拾氓,ViewModel層獲取到M層的數(shù)據(jù)后,通過觀察者模式通知AndroidDataBinding在UI上的改變底哥。缺點的話咙鞍,只能吐糟下AndroidDataBinding了,在xml中寫邏輯的時候趾徽,一點提示代碼都沒有续滋,感覺完全是在寫js似的,可讀性肯定對于初級的來說還是有點難看懂的孵奶。

android中用到的觀察者模式有哪些地方

觀察者模式是由一個發(fā)送者(發(fā)送者是筆者自己的稱呼疲酌,覺較之被觀察者貼切得多)和一個觀察者構(gòu)成的、發(fā)送者在狀態(tài)改變時(用戶操作了袁、程序主動改變等)主動通知所有觀察者作相應(yīng)的刷新朗恳。
android中最經(jīng)典要說ListView的數(shù)據(jù)源發(fā)生變化了,刷新列表的事例载绿。在setAdapter的時候粥诫,生成一個AdapterDataSetObserver,緊接著就是訂閱上該觀察者崭庸,該觀察者onChange方法里面有requestLayout方法转唉,該方法是觸發(fā)UI發(fā)生變化的方法。在BaseAdapter里面可以看到notifyDataSetChanged實際上觸發(fā)的是DataSetObservable被觀察者的notifyChanged方法急侥,notifyChanged會觸發(fā)AdapterDataSetObserveronChange方法。所以最終會走listView的requestLayout镰踏,最后刷新了UI。

說說google新出的Lifecycle框架

將類的生命周期方法移交到Lifecycle中管理搀玖,實現(xiàn)對類的生命周期的監(jiān)聽余境,從而在Lifecycle中處理生命周期的邏輯代碼。這里涉及到幾個對象:
LifecycleObserver接口( Lifecycle觀察者):實現(xiàn)該接口的類灌诅,通過注解的方式芳来,可以通過被LifecycleOwner類的addObserver(LifecycleObserver o)方法注冊,被注冊后,LifecycleObserver便可以觀察到LifecycleOwner的生命周期事件猜拾。
LifecycleOwner接口(Lifecycle持有者):實現(xiàn)該接口的類持有生命周期(Lifecycle對象)即舌,該接口的生命周期(Lifecycle對象)的改變會被其注冊的觀察者LifecycleObserver觀察到并觸發(fā)其對應(yīng)的事件。
Lifecycle(生命周期):和LifecycleOwner不同的是挎袜,LifecycleOwner本身持有Lifecycle對象顽聂,LifecycleOwner通過其Lifecycle getLifecycle()的接口獲取內(nèi)部Lifecycle對象。
State(當(dāng)前生命周期所處狀態(tài)):幾種事件狀態(tài)盯仪。
Event(當(dāng)前生命周期改變對應(yīng)的事件):當(dāng)Lifecycle發(fā)生改變紊搪,事件狀態(tài)的回調(diào)event。

okhttp原理

okhttp主要實現(xiàn)了異步全景、同步的網(wǎng)絡(luò)操作耀石,創(chuàng)建了不同的call對象,這里的call對象是一個個的runnable對象爸黄,由于我們的任務(wù)是很多的滞伟,因此這里有Dispatcher包裝了線程池來處理不同的call,其中該類中創(chuàng)建了三種隊列炕贵,分別用于存放正在執(zhí)行的異步任務(wù)梆奈,同步隊列,以及準(zhǔn)備的隊列称开。最后在執(zhí)行每個任務(wù)的時候亩钟,采用隊列的先進先出原則,處理每一個任務(wù)鳖轰,都是交給了后面的各種攔截器來處理清酥,有請求準(zhǔn)備的攔截器、緩存攔截器脆霎、網(wǎng)絡(luò)連接的攔截器总处,每一個攔截器組成了一個責(zé)任鏈的形式狈惫。到最后返回response信息睛蛛。
OkHttp的底層是通過Java的Socket發(fā)送HTTP請求與接受響應(yīng)的(這也好理解鹦马,HTTP就是基于TCP協(xié)議的),但是OkHttp實現(xiàn)了連接池的概念忆肾,即對于同一主機的多個請求荸频,其實可以公用一個Socket連接,而不是每次發(fā)送完HTTP請求就關(guān)閉底層的Socket客冈,這樣就實現(xiàn)了連接池的概念旭从。而OkHttp對Socket的讀寫操作使用的OkIo庫進行了一層封裝。

Retrofit原理

retrofit基于okHttp封裝成RESTFUL網(wǎng)絡(luò)請求框架场仲,通過工廠模式配置各種參數(shù)和悦,通過動態(tài)代理、注解實現(xiàn)網(wǎng)絡(luò)請求渠缕。retrofit利用了工廠模式鸽素,將分為生產(chǎn)網(wǎng)絡(luò)請求執(zhí)行器(callFactory)、回調(diào)方法執(zhí)行器(callbackExecutor)亦鳞、網(wǎng)絡(luò)請求適配器(CallAdapterFactory)馍忽、數(shù)據(jù)轉(zhuǎn)換器(converterFactory)等幾種工廠。
callFactory負(fù)責(zé)生產(chǎn)okHttp的call燕差,大家都知道okHttp通過生成call對象完成同步和異步的http請求遭笋。

callbackExecutor通過判斷不同的平臺,生成對應(yīng)平臺的數(shù)據(jù)回調(diào)執(zhí)行器徒探。其中android端的回調(diào)執(zhí)行器是通過handler回調(diào)數(shù)據(jù)瓦呼。

CallAdapterFactory是數(shù)據(jù)解析工廠,一般我們配置json的數(shù)據(jù)解析適配器就行刹帕。

converterFactory是數(shù)據(jù)轉(zhuǎn)換的工廠吵血,一般我們配置Rxjava的數(shù)據(jù)轉(zhuǎn)換就行。

retrofit通過動態(tài)代理模式實現(xiàn)接口類配置的注解偷溺、參數(shù)解析成HTTP對象蹋辅,最后通過okHttp實現(xiàn)網(wǎng)絡(luò)請求。

RecyclerView源碼挫掏、緩存分析

RecyclerView使用了強大的分工操作侦另,顯示、排版由LayoutManager處理尉共,數(shù)據(jù)顯示由adapter處理褒傅,item上下左右動態(tài)加入繪制由ItemDecoration處理,item的動畫由ItemAnimator處理袄友。面試主要分析recyclerView緩存殿托,recyclerView緩存是由內(nèi)部類Recycler維護,其中一級緩存有mAttachedScrap剧蚣,里面放的都是當(dāng)前屏幕正在顯示的viewHolder的緩存支竹,二級緩存是mCachedViews旋廷,里面放的都是移出到屏幕外的viewHolder緩存,mRecyclerPool是recyclerView的三級緩存礼搁,一般用在RecyclerView嵌套RecyclerView的時候用得到饶碘,比如外層的RecyclerView的item中有RecyclerView,那么里面的RecyclerView通過共用外層的RecyclerView的RecyclerPool來減少里面RecyclerView的ViewHolder創(chuàng)建馒吴。

Binder機制

binder機制是android端進程間通信的基石扎运,采用aidl的ipc通信方式,我們可以利用它來定義兩個進程相互通信的接口饮戳。他是基于Service實現(xiàn)的一種線程間通信機制豪治。它的本質(zhì)是C/S架構(gòu)的,需要一個服務(wù)器端扯罐,一個客戶端鬼吵。
AIDL通信方式里面有四個對象,一個是IInterface篮赢,專門用來負(fù)責(zé)接口的調(diào)度齿椅,Stub用來負(fù)責(zé)通信的響應(yīng)和發(fā)送給service端的數(shù)據(jù),Proxy負(fù)責(zé)兩個進程通信的包裝启泣,算是間接調(diào)用Stub的包裝類涣脚,service是服務(wù)端處理數(shù)據(jù)的關(guān)鍵類。用一張圖來表示如下:


圖片轉(zhuǎn)載

Android Jetpack

android jetpack是google專門為開發(fā)者快速開發(fā)app的一套組件寥茫,快速搭建mvvm框架的實現(xiàn)遣蚀,其中包括Lifecyle、LiveData纱耻、ViewModel芭梯、Room、DadaBinding弄喘、Navigation玖喘、Paging、WorkManager等一系列優(yōu)秀的框架蘑志。

Lifecycle:實現(xiàn)和activity累奈、fragment生命周期感知的框架,實現(xiàn)數(shù)據(jù)層和view層銷毀的時候解綁急但。原理是Lifecycler為每個活動組件添加了一個沒有界面的Fragment澎媒,利用Fragment周期會根據(jù)活動聲明周期變化的特性實現(xiàn)的特性,從而實現(xiàn)生命周期的感知波桩,然后根據(jù)注解的Event查找執(zhí)行相應(yīng)的方法戒努。

LiveData:提供了一種數(shù)據(jù)改變的同時,主動去告訴ui镐躲,讓ui層做出相應(yīng)的邏輯判斷储玫。原理是內(nèi)部保存了LifecycleOwner和Observer冬三,利用LifecycleOwner感知并處理聲明中期的變化,Observer在數(shù)據(jù)改變時遍歷所有觀察者并回調(diào)方法缘缚。

ViewModel:它是我們view層和model層的橋梁,是數(shù)據(jù)驅(qū)動界面的關(guān)鍵地方敌蚜,也是我們ui層在數(shù)據(jù)丟失的情況下桥滨,viewModel還能繼續(xù)保持原有的數(shù)據(jù),原理是將數(shù)據(jù)保存到ViewModel中弛车,然后為活動中添加一個HolderFragment齐媒,HolderFragment中保存了ViewStore的實例,ViewStore中使用Map保存了ViewModel纷跛,從而在活動重新創(chuàng)建時獲取到原來的ViewModel喻括。

Room:是model層本地數(shù)據(jù)庫的框架,通過實體映射到對應(yīng)的db表結(jié)構(gòu)贫奠,將實體映射到db關(guān)系型數(shù)據(jù)庫里面唬血。跟greendao差不多,room數(shù)據(jù)庫版本升級數(shù)據(jù)遷移比greendao遷移要麻煩唤崭,個人還是比較喜歡greendao來實現(xiàn)本地數(shù)據(jù)庫拷恨。
DadaBinding:是一個可以通過在xml布局文件中實現(xiàn)ui邏輯的框架,并且它的ui層和數(shù)據(jù)層雙向驅(qū)動還是挺不錯的谢肾。

Navigation:是后面新出來的可視化管理fragment的組件腕侄,通過在xml中配置fragment之間跳轉(zhuǎn)的關(guān)系。

Kotlin

kotlin使用了一組新的語法糖芦疏,kotlin不讓變量初始化空的類型冕杠,強大的非空設(shè)計思想比java要人性化,在代碼編寫階段就有提示開發(fā)者的好處酸茴。還有它的內(nèi)聯(lián)函數(shù)分预,函數(shù)體作為返回值的各種簡寫方式使更多的人愿意接受kotlin。它的協(xié)成開發(fā)比較好的控制線程之間切換的多層嵌套的問題薪捍,以及它簡潔的語法噪舀,比較受開發(fā)者青睞。

好了飘诗,大概android面試的android篇就寫這么多与倡。如果大家覺得還有那些要補上可以留言我!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市昆稿,隨后出現(xiàn)的幾起案子纺座,更是在濱河造成了極大的恐慌,老刑警劉巖溉潭,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件净响,死亡現(xiàn)場離奇詭異少欺,居然都是意外死亡,警方通過查閱死者的電腦和手機馋贤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門赞别,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人配乓,你說我怎么就攤上這事仿滔。” “怎么了犹芹?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵崎页,是天一觀的道長。 經(jīng)常有香客問我腰埂,道長飒焦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任屿笼,我火速辦了婚禮牺荠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驴一。我一直安慰自己志电,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布蛔趴。 她就那樣靜靜地躺著挑辆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孝情。 梳的紋絲不亂的頭發(fā)上鱼蝉,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音箫荡,去河邊找鬼魁亦。 笑死,一個胖子當(dāng)著我的面吹牛羔挡,可吹牛的內(nèi)容都是我干的洁奈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼绞灼,長吁一口氣:“原來是場噩夢啊……” “哼利术!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起低矮,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤印叁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轮蜕,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡昨悼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了跃洛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片率触。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖汇竭,靈堂內(nèi)的尸體忽然破棺而出葱蝗,到底是詐尸還是另有隱情,我是刑警寧澤韩玩,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站陆馁,受9級特大地震影響找颓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叮贩,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一击狮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧益老,春花似錦彪蓬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至桃纯,卻和暖如春酷誓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背态坦。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工盐数, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伞梯。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓玫氢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谜诫。 傳聞我的和親對象是個殘疾皇子漾峡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359