溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

騰訊Android社招面試源碼相關(guān)11題+原理詳解

發(fā)布時(shí)間:2020-02-28 00:38:06 來源:網(wǎng)絡(luò) 閱讀:830 作者:Android丶VG 欄目:移動(dòng)開發(fā)

對(duì)于這些專題的詳解,專門做了一個(gè)983頁(yè)的PDF版本,如下
騰訊Android社招面試源碼相關(guān)11題+原理詳解

(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取
(VX:mm14525201314)

Android源碼相關(guān)面試專題

1、Android屬性動(dòng)畫實(shí)現(xiàn)原理

工作原理 :在一定時(shí)間間隔內(nèi),通過不斷對(duì)值進(jìn)行改變,并不斷將該值賦給對(duì)象的屬性,從而實(shí)現(xiàn)該對(duì)象在該屬性上的動(dòng)畫效果。
騰訊Android社招面試源碼相關(guān)11題+原理詳解

1)ValueAnimator:通過不斷控制值的變化(初始值->結(jié)束值),將值手動(dòng)賦值給對(duì)象的屬性,再不斷調(diào)用View的invalidate()方法,去不斷onDraw重繪view,達(dá)到動(dòng)畫的效果。

主要的三種方法:

a)ValueAnimator.ofInt(int values):估值器是整型估值器IntEaluator

b)ValueAnimator.ofFloat(float values):估值器是浮點(diǎn)型估值器FloatEaluator

c)?ValueAnimator.ofObject(ObjectEvaluator, start, end):將初始值以對(duì)象的形式過渡到結(jié)束值,通過操作對(duì)象實(shí)現(xiàn)動(dòng)畫效果,需要實(shí)現(xiàn)Interpolator接口,自定義估值器??

估值器TypeEvalutor,設(shè)置動(dòng)畫如何從初始值過渡到結(jié)束值的邏輯。插值器(Interpolator)決定值的變化模式(勻速、加速等);估值器(TypeEvalutor)決定值的具體變化數(shù)值。

// 自定義估值器,需要實(shí)現(xiàn)TypeEvaluator接口
public class ObjectEvaluator implements TypeEvaluator{  

// 復(fù)寫evaluate(),在evaluate()里寫入對(duì)象動(dòng)畫過渡的邏輯
    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        // 參數(shù)說明
        // fraction:表示動(dòng)畫完成度(根據(jù)它來計(jì)算當(dāng)前動(dòng)畫的值)
        // startValue、endValue:動(dòng)畫的初始值和結(jié)束值
  ... // 寫入對(duì)象動(dòng)畫過渡的邏輯

        return value;  
        // 返回對(duì)象動(dòng)畫過渡的邏輯計(jì)算后的值
    } 
2)ObjectAnimator:直接對(duì)對(duì)象的屬性值進(jìn)行改變操作,從而實(shí)現(xiàn)動(dòng)畫效果

ObjectAnimator繼承自ValueAnimator類,底層的動(dòng)畫實(shí)現(xiàn)機(jī)制還是基本值的改變。它是不斷控制值的變化,再不斷自動(dòng)賦給對(duì)象的屬性,從而實(shí)現(xiàn)動(dòng)畫效果。這里的自動(dòng)賦值,是通過調(diào)用對(duì)象屬性的set/get方法進(jìn)行自動(dòng)賦值,屬性動(dòng)畫初始值如果有就直接取,沒有則調(diào)用屬性的get()方法獲取,當(dāng)值更新變化時(shí),通過屬性的set()方法進(jìn)行賦值。每次賦值都是調(diào)用view的postInvalidate()/invalidate()方法不斷刷新視圖(實(shí)際調(diào)用了onDraw()方法進(jìn)行了重繪視圖)。

//Object 需要操作的對(duì)象; propertyName 需要操作的對(duì)象的屬性; values動(dòng)畫初始值&結(jié)束值,
//如果是兩個(gè)值,則從a->b值過渡,如果是三值,則從a->b->c
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String propertyName, float ...values);

如果采用ObjectAnimator類實(shí)現(xiàn)動(dòng)畫,操作的對(duì)象的屬性必須有g(shù)et()和set()方法。

其他用法:

1)AnimatorSet組合動(dòng)畫

AnimatorSet.play(Animator anim)   :播放當(dāng)前動(dòng)畫
AnimatorSet.after(long delay)   :將現(xiàn)有動(dòng)畫延遲x毫秒后執(zhí)行
AnimatorSet.with(Animator anim)   :將現(xiàn)有動(dòng)畫和傳入的動(dòng)畫同時(shí)執(zhí)行
AnimatorSet.after(Animator anim)   :將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之后執(zhí)行
AnimatorSet.before(Animator anim) :  將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之前執(zhí)行

2) ViewPropertyAnimator直接對(duì)屬性操作,View.animate()返回的是一個(gè)ViewPropertyAnimator對(duì)象,之后的調(diào)用方法都是基于該對(duì)象的操作,調(diào)用每個(gè)方法返回值都是它自身的實(shí)例

View.animate().alpha(0f).x(500).y(500).setDuration(500).setInterpolator()

3)設(shè)置動(dòng)畫監(jiān)聽

Animation.addListener(new AnimatorListener() {
          @Override
public void onAnimationStart(Animation animation) {
              //動(dòng)畫開始時(shí)執(zhí)行
          }

           @Override
          public void onAnimationRepeat(Animation animation) {
              //動(dòng)畫重復(fù)時(shí)執(zhí)行
          }

         @Override
          public void onAnimationCancel()(Animation animation) {
              //動(dòng)畫取消時(shí)執(zhí)行
          }

          @Override
          public void onAnimationEnd(Animation animation) {
              //動(dòng)畫結(jié)束時(shí)執(zhí)行
          }
      });

2、補(bǔ)間動(dòng)畫實(shí)現(xiàn)原理

主要有四種AlpahAnimation\ ScaleAnimation\ RotateAnimation\ TranslateAnimation四種,對(duì)透明度、縮放、旋轉(zhuǎn)、位移四種動(dòng)畫。在調(diào)用View.startAnimation時(shí),先調(diào)用View.setAnimation(Animation)方法給自己設(shè)置一個(gè)Animation對(duì)象,再調(diào)用invalidate來重繪自己。在View.draw(Canvas, ViewGroup, long)方法中進(jìn)行了getAnimation(), 并調(diào)用了drawAnimation(ViewGroup, long, Animation, boolean)方法,此方法調(diào)用Animation.getTranformation()方法,再調(diào)用applyTranformation()方法,該方法中主要是對(duì)Transformation.getMatrix().setTranslate/setRotate/setAlpha/setScale來設(shè)置相應(yīng)的值,這個(gè)方法系統(tǒng)會(huì)以60FPS的頻率進(jìn)行調(diào)用。具體是在調(diào)Animation.start()方法中會(huì)調(diào)用animationHandler.start()方法,從而調(diào)用了scheduleAnimation()方法,這里會(huì)調(diào)用mChoreographer.postCallback(Choregrapher.CALLBACK_ANIMATION, this, null)放入事件隊(duì)列中,等待doFrame()來消耗事件。

當(dāng)一個(gè) ChildView要重畫時(shí),它會(huì)調(diào)用其成員函數(shù) invalidate() 函數(shù)將通知其 ParentView 這個(gè) ChildView 要重畫,這個(gè)過程一直向上遍歷到 ViewRoot,當(dāng) ViewRoot 收到這個(gè)通知后就會(huì)調(diào)用ViewRoot 中的 draw 函數(shù)從而完成繪制。View::onDraw() 有一個(gè)畫布參數(shù) Canvas, 畫布顧名思義就是畫東西的地方,Android 會(huì)為每一個(gè) View 設(shè)置好畫布,View 就可以調(diào)用 Canvas 的方法,比如:drawText, drawBitmap, drawPath 等等去畫內(nèi)容。每一個(gè) ChildView 的畫布是由其 ParentView設(shè)置的,ParentView 根據(jù) ChildView 在其內(nèi)部的布局來調(diào)整 Canvas,其中畫布的屬性之一就是定義和 ChildView 相關(guān)的坐標(biāo)系,默認(rèn)是橫軸為 X 軸,從左至右,值逐漸增大,豎軸為 Y 軸,從上至下,值逐漸增大。
騰訊Android社招面試源碼相關(guān)11題+原理詳解
Android 補(bǔ)間動(dòng)畫就是通過 ParentView 來不斷調(diào)整 ChildView的畫布坐標(biāo)系來實(shí)現(xiàn)的,在ParentViewdispatchDraw方法會(huì)被調(diào)用。

dispatchDraw() 
{ 
.... 
Animation a = ChildView.getAnimation() 
Transformation tm = a.getTransformation(); 
Use tm to set ChildView's Canvas; 
Invalidate(); 
.... 
}

這里有兩個(gè)類:Animation 和 Transformation,這兩個(gè)類是實(shí)現(xiàn)動(dòng)畫的主要的類,Animation 中主要定義了動(dòng)畫的一些屬性比如開始時(shí)間、持續(xù)時(shí)間、是否重復(fù)播放等,這個(gè)類主要有兩個(gè)重要的函數(shù):getTransformationapplyTransformation,在 getTransformation中 Animation 會(huì)根據(jù)動(dòng)畫的屬性來產(chǎn)生一系列的差值點(diǎn),然后將這些差值點(diǎn)傳給 applyTransformation,這個(gè)函數(shù)將根據(jù)這些點(diǎn)來生成不同的 Transformation,Transformation 中包含一個(gè)矩陣和 alpha 值,矩陣是用來做平移、旋轉(zhuǎn)和縮放動(dòng)畫的,而 alpha 值是用來做 alpha 動(dòng)畫的(簡(jiǎn)單理解的話,alpha 動(dòng)畫相當(dāng)于不斷變換透明度或顏色來實(shí)現(xiàn)動(dòng)畫),調(diào)用 dispatchDraw 時(shí)會(huì)調(diào)用 getTransformation來得到當(dāng)前的 Transformation。某一個(gè) View 的動(dòng)畫的繪制并不是由他自己完成的而是由它的父 view 完成。

補(bǔ)間動(dòng)畫TranslateAnimation,View位置移動(dòng)了,可是點(diǎn)擊區(qū)域還在原來的位置,為什么?

View在做動(dòng)畫是,根據(jù)動(dòng)畫時(shí)間的插值,計(jì)算出一個(gè)Matrix,不停的invalidate,在onDraw中的Canvas上使用這個(gè)計(jì)算出來的Matrix去draw view的內(nèi)容。

某個(gè)view的動(dòng)畫繪制并不是由它自己完成,而是由它的父view完成,使它的父view畫布進(jìn)行了移動(dòng),而點(diǎn)擊時(shí)還是點(diǎn)擊原來的畫布。使得它看起來變化了。

3、Android各個(gè)版本API的區(qū)別

主要記住一些大版本變化:

  • android3.0 代號(hào)Honeycomb, 引入Fragments, ActionBar,屬性動(dòng)畫,硬件加速

  • android4.0 代號(hào)Ice Cream,API14:截圖功能,人臉識(shí)別,虛擬按鍵,3D優(yōu)化驅(qū)動(dòng)

  • android5.0 代號(hào)Lollipop API21:調(diào)整桌面圖標(biāo)及部件透明度等

  • android6.0 代號(hào)M Marshmallow API23,軟件權(quán)限管理,安卓支付,指紋支持,App關(guān)聯(lián),

  • android7.0 代號(hào)N Preview API24,多窗口支持(不影響Activity生命周期),增加了JIT編譯器,引入了新的應(yīng)用簽名方案APK Signature Scheme v2(縮短應(yīng)用安裝時(shí)間和更多未授權(quán)APK文件更改保護(hù)),嚴(yán)格了權(quán)限訪問
  • android8.0 代號(hào)O? API26,取消靜態(tài)廣播注冊(cè),限制后臺(tái)進(jìn)程調(diào)用手機(jī)資源,桌面圖標(biāo)自適應(yīng)

  • android9.0 代號(hào)P API27,加強(qiáng)電池管理,系統(tǒng)界面添加了Home虛擬鍵,提供人工智能API,支持免打擾模式

4、Requestlayout,onlayout,onDraw,DrawChild區(qū)別與聯(lián)系

requestLayout()方法 :會(huì)導(dǎo)致調(diào)用measure()過程 和 layout()過程 。 說明:只是對(duì)View樹重新布局layout過程包括measure()和layout()過程,如果view的l,t,r,b沒有必變,那就不會(huì)觸發(fā)onDraw;但是如果這次刷新是在動(dòng)畫里,mDirty非空,就會(huì)導(dǎo)致onDraw。

onLayout()方法(如果該View是ViewGroup對(duì)象,需要實(shí)現(xiàn)該方法,對(duì)每個(gè)子視圖進(jìn)行布局)

onDraw()方法繪制視圖本身 (每個(gè)View都需要重載該方法,ViewGroup不需要實(shí)現(xiàn)該方法)

drawChild()去重新回調(diào)每個(gè)子視圖的draw()方法

5、invalidate和postInvalidate的區(qū)別及使用

View.invalidate():?層層上傳到父級(jí),直到傳遞到ViewRootImpl后觸發(fā)了scheduleTraversals(),然后整個(gè)View樹開始重新按照View繪制流程進(jìn)行重繪任務(wù)。

invalidate:在ui線程刷新view
postInvalidate:在工作線程刷新view(底層還是handler)其實(shí)它的原理就是invalidate+handler
View.postInvalidate最終會(huì)調(diào)用ViewRootImpl.dispatchInvalidateDelayed()方法

public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
        Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
        mHandler.sendMessageDelayed(msg, delayMilliseconds);
    }

這里的mHandlerViewRootHandler實(shí)例,在該Handler的handleMessage方法中調(diào)用了view.invalidate()方法。

case MSG_INVALIDATE:
                    ((View) msg.obj).invalidate();
break;

6、Activity-Window-View三者的差別

Activity:是安卓四大組件之一,負(fù)責(zé)界面展示、用戶交互與業(yè)務(wù)邏輯處理;
Window:就是負(fù)責(zé)界面展示以及交互的職能部門,就相當(dāng)于Activity的下屬,Activity的生命周期方法負(fù)責(zé)業(yè)務(wù)的處理;
View:就是放在Window容器的元素,Window是View的載體,View是Window的具體展示。
三者的關(guān)系:?Activity通過Window來實(shí)現(xiàn)視圖元素的展示,window可以理解為一個(gè)容器,盛放著一個(gè)個(gè)的view,用來執(zhí)行具體的展示工作。
騰訊Android社招面試源碼相關(guān)11題+原理詳解

7、談?wù)剬?duì)Volley的理解

8、如何優(yōu)化自定義View

1)在要在onDraw或是onLayout()中去創(chuàng)建對(duì)象,因?yàn)?code>onDraw()方法可能會(huì)被頻繁調(diào)用,可以在view的構(gòu)造函數(shù)中進(jìn)行創(chuàng)建對(duì)象;

2)降低view的刷新頻率,盡可能減少不必要的調(diào)用invalidate()方法?;蚴钦{(diào)用帶四種參數(shù)不同類型的invalidate(),而不是調(diào)用無參的方法。無參變量需要刷新整個(gè)view,而帶參數(shù)的方法只需刷新指定部分的view。在onDraw()方法中減少冗余代碼。

3)使用硬件加速,GPU硬件加速可以帶來性能增加。

4)狀態(tài)保存與恢復(fù),如果因內(nèi)存不足,Activity置于后臺(tái)被殺重啟時(shí),View應(yīng)盡可能保存自己屬性,可以重寫onSaveInstanceStateonRestoreInstanceState方法,狀態(tài)保存。

9、低版本SDK如何實(shí)現(xiàn)高版本api?

使用@TargetApi注解·
當(dāng)代碼中有比AndroidManifest中設(shè)置的android:minSdkVersion版本更高的方法,此時(shí)編譯器會(huì)提示警告,解決方法是在方法上加上

@SuppressLint("NewApi")或者@TargetApi()。但它們僅是屏蔽了android lint錯(cuò)誤,在方法中還要判斷版本做不同的操作。

@SuppressLint("NewApi")屏蔽一切新api中才能使用的方法報(bào)的android lint錯(cuò)誤

@TargetApi()只屏蔽某一新api中才能使用的方法報(bào)的android lint錯(cuò)誤,如@TargetApi(11)如果在方法中用了只有API14才開始有的方法,還是會(huì)報(bào)錯(cuò)。

10、描述一次網(wǎng)絡(luò)請(qǐng)求的流程

1)域名解析

瀏覽器會(huì)先搜索自身DNS緩存且對(duì)應(yīng)的IP地址沒有過期;若未找到則搜索操作系統(tǒng)自身的DNS緩存;若還未找到則讀本地的hotsts文件;還未找到會(huì)在TCP/IP設(shè)置的本地DNS服務(wù)器上找,如果要查詢的域名在本地配置的區(qū)域資源中,則完成解析;否則根據(jù)本地DNS服務(wù)器會(huì)請(qǐng)求根DNS服務(wù)器;根DNS服務(wù)器是13臺(tái)根DNS,會(huì)一級(jí)一級(jí)往下找。

2)TCP三次握手

客戶端先發(fā)送SYN=1,ACK=0,序列號(hào)seq=x報(bào)文;(SYN在連接建立時(shí)用來同步序號(hào),SYN=1,ACK=0代表這是一個(gè)連接請(qǐng)求報(bào)文,對(duì)方若同意建立連接,則應(yīng)在響應(yīng)報(bào)文中使SYN=1,ACK=1)

服務(wù)器返回SYN=1,ACK=1,seq=y, ack=x+1;

客戶端再一次確認(rèn),但不用SYN了,回復(fù)服務(wù)端, ACK=1, seq=x+1, ack=y+1

3)建立TCP連接后發(fā)起HTTP請(qǐng)求

客戶端按照指定的格式開始向服務(wù)端發(fā)送HTTP請(qǐng)求,HTTP請(qǐng)求格式由四部分組成,分別是請(qǐng)求行、請(qǐng)求頭、空行、消息體,服務(wù)端接收到請(qǐng)求后,解析HTTP請(qǐng)求,處理完成邏輯,最后返回一個(gè)具有標(biāo)準(zhǔn)格式的HTTP響應(yīng)給客戶端。

4)服務(wù)器響應(yīng)HTTP請(qǐng)求

服務(wù)器接收處理完請(qǐng)求后返回一個(gè)HTTP響應(yīng)消息給客戶端,HTTP響應(yīng)信息格式包括:狀態(tài)行、響應(yīng)頭、空行、消息體

5)瀏覽器解析HTML代碼,請(qǐng)求HTML代碼中的資源

瀏覽器拿到html文件后,就開始解析其中的html代碼,遇到j(luò)s/css/image等靜態(tài)資源時(shí),向服務(wù)器發(fā)起一個(gè)http請(qǐng)求,如果返回304狀態(tài)碼,瀏覽器會(huì)直接讀取本地的緩存文件。否則開啟線程向服務(wù)器請(qǐng)求下載。

6)瀏覽器對(duì)頁(yè)面進(jìn)行渲染并呈現(xiàn)給用戶

7)TCP的四次揮手

當(dāng)客戶端沒有東西要發(fā)送時(shí)就要釋放連接(提出中斷連接可以是Client也可以是Server),客戶端會(huì)發(fā)送一個(gè)FIN=1的沒有數(shù)據(jù)的報(bào)文,進(jìn)入FIN_WAIT狀態(tài),服務(wù)端收到后會(huì)給客戶端一個(gè)確認(rèn),此時(shí)客戶端不能發(fā)送數(shù)據(jù),但可接收信息。

11、HttpUrlConnection 和 okhttp關(guān)系

兩者都可以用來實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求,android4.4之后的HttpUrlConnection的實(shí)現(xiàn)是基于okhttp

  • Bitmap對(duì)象的理解
  • looper架構(gòu)
  • ActivityThread,AMS,WMS的工作原理
  • 自定義View如何考慮機(jī)型適配

onMeasure()getDefaultSize()的默認(rèn)實(shí)現(xiàn)中,當(dāng)view的測(cè)量模式是AT_MOST或EXACTLY時(shí),View的大小都會(huì)被設(shè)置成子View MeasureSpecspecSize.子view的MeasureSpec值是根據(jù)子View的布局參數(shù)和父容器的MeasureSpec值計(jì)算得來。當(dāng)子view的布局參數(shù)是wrap_content時(shí),對(duì)應(yīng)的測(cè)量模式是AT_MOST,大小是parentSize,

  • 自定義View的事件
  • AstncTask+HttpClient 與 AsyncHttpClient有什么區(qū)別?
  • LaunchMode應(yīng)用場(chǎng)景
  • AsyncTask 如何使用?
  • SpareArray原理
  • 請(qǐng)介紹下ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的?
  • AndroidService與Activity之間通信的幾種方式
  • IntentService原理及作用是什么?

原理IntentService是繼承Service的一個(gè)抽象類,它在onCreate()方法中創(chuàng)建了一個(gè)HandlerThread,并啟動(dòng)該線程。HandlerThread是帶有自己消息隊(duì)列和Looper的線程,根據(jù)HandlerThreadlooper創(chuàng)建一個(gè)Handler,這樣IntentServiceServiceHandlerhandleMessage()方法就運(yùn)行在子線程中。handleMessage中調(diào)用了onHandleIntent()方法,它是一個(gè)抽象方法,繼承IntentService類需要實(shí)現(xiàn)該方法,把耗時(shí)操作放在onHandleIntent()方法中,等耗時(shí)操作運(yùn)行完成后,會(huì)調(diào)用stopSelf()方法,服務(wù)會(huì)調(diào)用onDestory()方法消毀自己。如果onHandleIntent()中的耗時(shí)操作未運(yùn)行完前就調(diào)用了stopSelf()方法,服務(wù)調(diào)用onDestory()方法,但耗時(shí)操作會(huì)繼續(xù)運(yùn)行,直至運(yùn)行完畢。如果同時(shí)多次啟動(dòng)IntentService,任務(wù)會(huì)放在一個(gè)隊(duì)列中,onCreate()onDestory()方法都只會(huì)運(yùn)行一次。

作用:用來處理后臺(tái)耗時(shí)操作,如讀取數(shù)據(jù)庫(kù)或是本地文件等。

  • 說說Activity、Intent、Service 是什么關(guān)系
  • ApplicationContext和ActivityContext的區(qū)別
  • SP是進(jìn)程同步的嗎?有什么方法做到同步?
  • 談?wù)劧嗑€程在Android中的使用
  • 進(jìn)程和 Application 的生命周期
  • 封裝View的時(shí)候怎么知道view的大小
  • RecycleView原理
  • AndroidManifest的作用與理解

(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
領(lǐng)取完整版PDF

騰訊Android社招面試源碼相關(guān)11題+原理詳解

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI