2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享_第1頁(yè)
2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享_第2頁(yè)
2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享_第3頁(yè)
2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享_第4頁(yè)
2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀 繼續(xù)免費(fèi)閱讀

2025年Android-值得深入思考的幾個(gè)面試問(wèn)答分享.docx 免費(fèi)下載

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

先自我介紹下,作者浙大畢業(yè),去過(guò)小公司,也曾任職華為、字節(jié)跳動(dòng)等大廠,現(xiàn)為阿里技術(shù)專家。專注移動(dòng)開(kāi)發(fā)領(lǐng)域,尤其擅長(zhǎng)Android技術(shù)棧與跨平臺(tái)解決方案。我收集整理了一份《2025年最新Android移動(dòng)開(kāi)發(fā)全套學(xué)習(xí)資料》,希望能夠幫助到想自學(xué)提升又不知道該從何學(xué)起的朋友??體系化內(nèi)容?:覆蓋Android開(kāi)發(fā)95%核心知識(shí)點(diǎn),包含零基礎(chǔ)入門到高級(jí)進(jìn)階課程?實(shí)戰(zhàn)資源?:整合大廠面經(jīng)、源碼項(xiàng)目、性能優(yōu)化方案及持續(xù)更新技術(shù)棧?附加服務(wù)?:提供技術(shù)交流/職場(chǎng)規(guī)劃/內(nèi)推機(jī)會(huì),助力開(kāi)發(fā)者突破成長(zhǎng)瓶頸需要的朋友可以十我徽心獲取全套資料:vip204888(備注Android)###前言移動(dòng)開(kāi)發(fā)技術(shù)手段從原始的原生應(yīng)用開(kāi)發(fā),到Google和Apple各自推出新的語(yǔ)言Kotiln、Swift,然后又發(fā)展到各種跨平臺(tái)HybridApp開(kāi)發(fā),如ReactNative、Weex、小程序等等。不過(guò)這些方案或多或少都有一些局限性和缺點(diǎn),于是Google推出了新的跨平臺(tái)移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù):Flutter。為什么說(shuō)Flutter將是未來(lái)的主流跨平臺(tái)開(kāi)發(fā)框架?Google的Flutter開(kāi)發(fā)應(yīng)用的體驗(yàn)和流暢度基本和原生體驗(yàn)一致,感覺(jué)不到不流暢和卡頓。我們知道在移動(dòng)平臺(tái)上,原生應(yīng)用的體驗(yàn)最好、流暢度最高、性能也最好。而目前的跨平臺(tái)技術(shù)和框架的流暢度和體驗(yàn)遠(yuǎn)遠(yuǎn)達(dá)不到原生的體驗(yàn),多少都會(huì)卡頓和丟幀,但是Google官方說(shuō)Flutter可以達(dá)到120FPS。Flutter最出色的地方就是自建了繪制引擎,使得跨平臺(tái)開(kāi)發(fā)一套代碼可以創(chuàng)造出和原生應(yīng)用相同的體驗(yàn)。并且Flutter開(kāi)發(fā)效率非常高,SDK里所有的布局、控件都組件化,采用React方式。金九銀十面試季又要到來(lái)了,這里給大家不定期更新大廠面試真題,今天來(lái)分享一下Android面試中幾個(gè)值得我們深入思考的面試題還有解析,希望可以幫助到即將面試的小伙伴們,祝面試順利~####1.

事件分發(fā)機(jī)制大家應(yīng)該都熟記于心,默認(rèn)事件分發(fā)是逆序的,有哪些方法可以修改分發(fā)順序?記得曾經(jīng)有位朋友做貼紙應(yīng)用時(shí),有RT的需求。默認(rèn)事件分發(fā)為逆序,遍歷子View為(childCount~0],有哪些方式可以修改這一策略,比如修改遍歷方式為[0,childCount)?修改事件分發(fā)順序的話,在日常開(kāi)發(fā)中基本遇不到,因?yàn)楝F(xiàn)在的逆序遍歷,是跟View的層級(jí)顯示相匹配的,隨便更改反而不太合理。如果非要修改這個(gè)順序,很多同學(xué)首先會(huì)想到:重寫dispatchTouchEvent方法,然后在里面一個(gè)for循環(huán),從0開(kāi)始一個(gè)個(gè)調(diào)用子View的dispatchTouchEvent。這個(gè)方法,不是說(shuō)絕對(duì)不行,只是你要做的事情很多,就比如觸摸坐標(biāo)的轉(zhuǎn)換:我們都知道,ViewGroup在分派事件的時(shí)候,會(huì)檢查子View是否應(yīng)用過(guò)屬性動(dòng)畫的(位移、縮放、旋轉(zhuǎn)等),如果有的話還要把坐標(biāo)給映射回去。接著,還會(huì)把相對(duì)于這個(gè)ViewGroup本身的觸摸坐標(biāo)轉(zhuǎn)換成相對(duì)于對(duì)應(yīng)子View的觸摸坐標(biāo)。這樣說(shuō)可能有點(diǎn)繞,舉個(gè)例子:比如:當(dāng)手指在屏幕中按下,ViewGroup中收到的event坐標(biāo)(getX,getY)假設(shè)是【500,500】,剛好在這個(gè)位置上有個(gè)子View,那接下來(lái)肯定會(huì)把事件傳給這個(gè)子View的dispatchTouchEvent,這時(shí)候如果坐標(biāo)不轉(zhuǎn)換直接傳的話,那子View收到的event坐標(biāo)(getX,getY)也是【500,500】,這明顯是不對(duì)的,正確的坐標(biāo)應(yīng)該要分別減去它的left和top。這看起來(lái)好像沒(méi)什么大的影響,但如果你的子View沒(méi)有重寫onTouchEvent方法的話(比如子View是常用的ImageView,TextView之類的),你的OnClickListener就會(huì)無(wú)效了,因?yàn)槟J(rèn)的onTouchEvent在處理ACTION_MOVE的時(shí)候,會(huì)檢查event的坐標(biāo)是否已經(jīng)脫離了View的邊界范圍,如果在邊界范圍之外的話,pressed將會(huì)失效(認(rèn)為沒(méi)有被按下),當(dāng)ACTION_UP時(shí),如果pressed為false,就不會(huì)執(zhí)行PerformClick。那難道沒(méi)有方法可以完美地做到了嗎?在ViewGroup的dispatchTouchEvent方法中,雖然它是逆序的for,但是呢,它把子View拿出來(lái)的時(shí)候,卻不是直接操作的mChildren數(shù)組,而是通過(guò)一個(gè)getAndVerifyPreorderedView方法來(lái)獲得,這個(gè)方法會(huì)把當(dāng)前索引傳進(jìn)去,還有一個(gè)preorderedList。@OverridepublicbooleandispatchTouchEvent(MotionEventev){//…

finalArrayListpreorderedList=buildTouchDispatchChildList();finalbooleancustomOrder=preorderedList==null&&isChildrenDrawingOrderEnabled();finalView[]children=mChildren;for(inti=childrenCount-1;i>=0;i–){finalintchildIndex=getAndVerifyPreorderedIndex(childrenCount,i,customOrder);finalViewchild=getAndVerifyPreorderedView(preorderedList,children,childIndex);…}如果傳進(jìn)去的preorderedList不為空,那么就會(huì)直接從它里面去取。####preorderedList怎么來(lái)?通過(guò)調(diào)用buildOrderedChildList方法獲取的。buildOrderedChildList方法是怎么樣的?ArrayListbuildOrderedChildList(){finalintchildrenCount=mChildrenCount;if(childrenCount<=1||!hasChildWithZ())returnnull;if(mPreSortedChildren==null){mPreSortedChildren=newArrayList<>(childrenCount);}else{//callersshouldclear,soclearshouldn’tbenecessary,butforsafety…mPreSortedChildren.clear();mPreSortedChildren.ensureCapacity(childrenCount);}finalbooleancustomOrder=isChildrenDrawingOrderEnabled();for(inti=0;i<childrenCount;i++){//addnextchild(inchildorder)toendoflistfinalintchildIndex=getAndVerifyPreorderedIndex(childrenCount,i,customOrder);finalViewnextChild=mChildren[childIndex];finalfloatcurrentZ=nextChild.getZ();//insertaheadofanyViewswithgreaterZintinsertIndex=i;while(insertIndex>0&&mPreSortedChildren.get(insertIndex-1).getZ()>currentZ){insertIndex–;}mPreSortedChildren.add(insertIndex,nextChild);}returnmPreSortedChildren;}它里面是通過(guò)一個(gè)getAndVerifyPreorderedIndex方法來(lái)獲取對(duì)應(yīng)的子VIew索引,這個(gè)方法要傳進(jìn)去一個(gè)叫customOrder的boolean。這個(gè)customOrder,看名字可以知道,是自定義順序的意思,如果它為true的話,接著會(huì)通過(guò)getChildDrawingOrder(intchildCount,inti)方法來(lái)獲取對(duì)應(yīng)的索引,而且,這個(gè)方法是protected的,所以我們可以通過(guò)重寫這個(gè)方法并根據(jù)參數(shù)“i”來(lái)決定返回哪一個(gè)View所對(duì)應(yīng)的索引,從而改變分發(fā)的順序。protectedintgetChildDrawingOrder(intchildCount,inti){returni;}那這個(gè)customOrder,什么時(shí)候?yàn)閠rue呢?在buildOrderedChildList方法里可以看到這么一句:final

boolean

customOrder

=

isChildrenDrawingOrderEnabled();emmmm,也就是說(shuō),如果要自定義這個(gè)順序的話,還需要調(diào)用setChildrenDrawingOrderEnabled(true)來(lái)開(kāi)啟。重新捋一捋流程:1.setChildrenDrawingOrderEnabled(true)來(lái)開(kāi)啟自定義順序;2.重寫getChildDrawingOrder方法來(lái)決定什么時(shí)候要返回哪個(gè)子View;###2.

AppCompatTextView與TextView有什么區(qū)別?1.compat庫(kù)是如何將TextView替換為AppCompatTextVew的?2.為什么要進(jìn)行替換?3.根據(jù)替換相關(guān)原理,我們可以做哪些事情?####先從第二問(wèn)開(kāi)始吧:AppCompatTextView繼承自TextView,是對(duì)TextView的一種擴(kuò)展,因?yàn)樵?.0中首次推出了MaterialDesign這種設(shè)計(jì)風(fēng)格。但是眾所周知的,5.0推出不可能所有的設(shè)備全都一下子更新到最新版本,為了在早期版本上實(shí)現(xiàn)新的功能(這些新功能比如從源碼注釋中解讀到比如backgroundTint屬性,根據(jù)文本內(nèi)容自適應(yīng)大小等).即為了新特性同樣可以兼容老版本,framework在創(chuàng)建TextView實(shí)例的時(shí)候,自動(dòng)幫我們進(jìn)行了替換。其它的AppCompatXXX與XXX的關(guān)系也是如此。####第一問(wèn):然后第一問(wèn),如何完成替換的,我們這里只拿最直觀的流程舉例,且盡可能的簡(jiǎn)化源碼過(guò)程,在討論這個(gè)問(wèn)題之前,先了解幾個(gè)預(yù)備知識(shí):View是怎么被解析創(chuàng)建出來(lái)的:1.LayoutInflater:將布局XML文件實(shí)例化為其對(duì)應(yīng)的View對(duì)象,我們?cè)贏ctivity中通過(guò)setContentView傳入一個(gè)Layout的資源文件id,最終該方法最終會(huì)調(diào)用到PhoneWindow的setContentView方法,這個(gè)方法里面有調(diào)用到mLayoutInflater.inflate(layoutResID,

mContentParent);2.inflate方法,該方法的作用是將指定的XML文件填充到View的層次結(jié)構(gòu)中去,最終無(wú)論通過(guò)什么途徑調(diào)用到inflate方法,都會(huì)走到三個(gè)參數(shù)的重載方法這里:return

inflate(parser,

root,

attachToRoot);parser你可以認(rèn)為持有將Layout.XML解析后的數(shù)據(jù)。后兩個(gè)參數(shù)的意義如下:1.root為null,attchToRoot無(wú)意義,inflate返回的是當(dāng)前XML對(duì)應(yīng)的根布局。2.root不為null且attachToRoot為true,則整個(gè)XML對(duì)應(yīng)的布局就設(shè)置了根布局是root。3.root不為null且attachToRoot為false,則會(huì)將root的layoutParames設(shè)置給當(dāng)前XML的布局。知道了LayoutInflate.inflate做了什么,再往下,inflate中會(huì)調(diào)用createViewFromTag,從方法名就能知道,繼續(xù)往下走,我們離答案越來(lái)越近了。createViewFromTag做的事情非常有意思:先看到787行這個(gè)if-else,條件是name中有沒(méi)有“.”字符,如果有我們會(huì)執(zhí)行onCreateView,如果沒(méi)有會(huì)執(zhí)行createView。####name啥時(shí)候有點(diǎn)?自定義控件的時(shí)候。當(dāng)是系統(tǒng)控件的時(shí)候,createView會(huì)有一個(gè)填充了第二個(gè)參數(shù)的調(diào)用:createView(name,“android.view.”,attrs);補(bǔ)上了View控件的全路徑名,而自定義控件則不需要,因?yàn)閭魅氲膎ame就是一個(gè)全路徑名。####為什么要全路徑名?因?yàn)閂iew控件對(duì)象的創(chuàng)建是通過(guò)反射來(lái)實(shí)現(xiàn)的:clazz=mContext.getClassLoader().loadClass(prefix!=null?(prefix+name):name).asSubclass(View.class);…constructor=clazz.getConstructor(mConstructorSignature);constructor.setAccessible(true);sConstructorMap.put(name,constructor);//…args[1]=attrs;finalViewview=constructor.newInstance(args);下面對(duì)這幾步做一個(gè)總結(jié):XML中保存了ViewTree的結(jié)構(gòu)和View的相關(guān)標(biāo)簽信息(包括View的類型和一些屬性值),然后這些信息會(huì)在后面通過(guò)反射的方式(如果沒(méi)有Factory2和Factory的話)創(chuàng)建實(shí)例對(duì)象,如果創(chuàng)建的是ViewGroup,則會(huì)對(duì)它的子View遍歷重復(fù)創(chuàng)建步驟,創(chuàng)建完View對(duì)象后,會(huì)add到對(duì)應(yīng)的ViewGroup中。其中相關(guān)方法的調(diào)用流程是:inflate->rInflate->createViewFromTag->createView。好像還是沒(méi)有看到替換?還是上一張圖,我們只解釋了后半部分,沒(méi)有解釋前半部分,那么什么是Factory?繼續(xù)往下看:createViewFromTag中會(huì)先判斷有沒(méi)有Factory或者Factory2的對(duì)象,如果有,則調(diào)用Factory的onCreateView方法。這兩個(gè)類都是接口,其中Factory2是Factory的子接口,都只有唯一一個(gè)onCreateView方法。不同之處在于Factory2的onCreateView方法傳入了parentView。該方法的作用就是你可以借助它來(lái)改造XML中已經(jīng)存在了的Tag的值。所以Factory2可以達(dá)到改造parentView的目的。但是我們?cè)谌粘V懈揪蜎](méi)有任何地方接觸到了Factory(2)呀,那么它是不是就直接是null呢?到這里又是一番源碼調(diào)來(lái)調(diào)去,為了便于理解,只需要知道,這個(gè)東西(Factory2),在最開(kāi)始AppCompatActivity(為了兼容低版本,我們現(xiàn)在Activity默認(rèn)都是繼承自它)中的onCreate方法中就已經(jīng)通過(guò)層層調(diào)用被設(shè)置好了。既然現(xiàn)在Factory2不為空,那么就應(yīng)該去走它的onCreateView方法了,這里又是層層調(diào)用,最終來(lái)到了AppCompatViewInflater

的createView方法:答案就在這里:如果創(chuàng)建的是非兼容控件(系統(tǒng)控件那么多,實(shí)現(xiàn)兼容的只是常用的一些控件),那么就會(huì)是143行,在146中通過(guò)反射創(chuàng)建View對(duì)象。啰里啰唆扯了一大堆,還是沒(méi)回答第一個(gè)問(wèn)題:####compat庫(kù)是如何將TextView替換為AppCompatTextVew的?個(gè)人對(duì)這個(gè)的理解:在將XML文件解析成包含ViewTree信息之后,開(kāi)始利用這些信息去創(chuàng)建每一個(gè)View節(jié)點(diǎn),在創(chuàng)建View對(duì)象的時(shí)候,如果發(fā)現(xiàn)這個(gè)節(jié)點(diǎn)是屬于支持兼容的控件比如TextView,那么就會(huì)去調(diào)用到newAppCompatTextView()來(lái)創(chuàng)建一個(gè)兼容的View對(duì)象,也就是在創(chuàng)建的時(shí)候,及已經(jīng)實(shí)現(xiàn)了替換。第三問(wèn):根據(jù)替換相關(guān)原理,我們可以做哪些事情?整個(gè)替換從圖一所示的源碼中可以看到,能夠被替換的關(guān)鍵是Factory(2)存在,那么我覺(jué)得,其實(shí)問(wèn)題問(wèn)的是Factory(2)可以用來(lái)做什么吧?那么這個(gè)時(shí)候,就適合去問(wèn)站長(zhǎng)大人了:探究LayoutInflatersetFactory###3.

getWidth,getMeasuredWidth有什么區(qū)別?getWidth和getMeasuredWidth的區(qū)別:getMeasuredWidth方法返回的是測(cè)量后的寬度,這個(gè)寬度是當(dāng)setMeasuredDimension方法(measure方法最終會(huì)調(diào)用setMeasuredDimension)被調(diào)用后刷新的。而getWidth返回的是最終layout出來(lái)的寬度,在View代碼中返回的是【mRight-mLeft】,這個(gè)mRight和mLeft,是在setFrame方法被調(diào)用后賦值的(layout方法最終會(huì)調(diào)用setFrame)。也就是說(shuō),getMeasuredWidth返回值的大小,取決于setMeasuredDimension,而getWidth,則取決于layout。傳說(shuō)中一個(gè)是View寬度,一個(gè)是View中的內(nèi)容寬度,這個(gè)解答對(duì)嗎?在常規(guī)的View中,比如TextView,ImageView這些,如果沒(méi)有明確指定寬度的話,那么他們的getMeasuredWidth返回的寬度,確實(shí)就是實(shí)際內(nèi)容的寬度。但如果在xml布局里或自定義View中故意把寬度設(shè)置的很大,或者很小,比如設(shè)置寬度為9999999,這種情況就不算了。所以我的回答是:如果這個(gè)View和它所在的ViewGroup(在ViewGroup中的onMeasure也可做手腳),都遵守規(guī)矩的話

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論