這些分析加上這13道面試題,面試足矣

前言

其實對於很多人來說,都和我原來有同樣一個疑慮:**到底去大廠還是創業型公司?**去大公司一個蘿蔔一個坑,要往上走需要運氣+實力足夠好才能脫穎而出,創業型公司,可能更容易實現自己的想法和舞臺,能把能力表現的淋漓盡致,可是會碰到更多的問題,公司經營不下去了怎麼辦?薪資待遇不如大廠?

一丶大廠offer?

我相信每個程序員的夢想都是得到大廠的offer,我覺得這很正常,這並不是我們的飯後談資而是每個技術人的追求。像阿里、騰訊、美團、字節跳動、京東等等的技術氛圍與技術規範度還是要明顯優於一些創業型公司/小公司,如果說能夠在這樣的公司鍛鍊幾年,相信對自己能力的提升還是非常大的。但不是每個人都能夠進入大廠的,這往往取決於我們的能力、學歷、面試表現等因素。

現在面試大公司你說你沒有架構開發經驗估計都拿不出手,熱修復,框架,glide,OKHTTP,flutter,NDK,音視頻~源碼原理等等已然大廠面試所必須的知識。但是,你真進入大廠了,可能幾年都用不上這些知識,還是老老實實去寫代碼。

二丶抱怨不如努力提升自我

相比於前幾年來說,現在的面試難度提升了不少。你說說現在程序員這麼多,你投遞的公司可能與你一起投遞的就有300人,可人家只招5人,那怎麼辦?簡歷PASS掉一大批,然後面試再PASS掉一大批。從這樣來看,現在流行說的:**“面試造火箭,工作擰螺絲”**還是很有道理的,提高面試難度只是爲了從很多人中招到自己需要的那些人。

很多人都抱怨現在工作越來越難找了,的確,互聯網行業現在確實沒有之前好找工作了。我覺得有

1丶很大一部分對自己的技術的認識還停留在過去的那一兩年,
2丶是半路出家的人的基礎肯定是沒有大學習踏實學習計算機知識的人好的,這就造成很多培訓班出生的人很難往前走;
3丶是互聯網行業確實對年輕的人有一部分偏愛,畢竟剛畢業的大學生還是比較廉價的,但是互聯網行業並不是吃青春飯。
4.市場逐漸趨於完善,每個崗位對技術的要求越來越嚴謹,造成一種飽和不缺人的現象。
5.高級開發越來卻越缺人,中低級市場飽和

所以,不管是應屆生還是工作幾年的小夥伴都要對自己有一個清晰的認識,搞清楚你自己所欠缺的能力,搞清楚你自己的優勢(企業爲什麼要招你)。知道自己不足的地方之後,就要去努力!

互聯網行業其實還是挺公平的,雖然面試的時候會將你的學歷作爲參考,但是如果你的能力真的厲害,你的簡歷真的豐富的話,面試官還是會很欣賞這樣的應聘者的。

三丶如何清晰的認知自己的不足,提升個人實力

我在這裏所說的個人硬實力更多的指的是個人的專業能力,比如構建高質量網站的能力或者是對專業知識的掌握程度。

我覺得不論是對於新手還是老手,想要提高個人硬實力最重要的就是不斷深入學習並且將理論實踐,最好可以將理論在具體項目中實踐一下。

給還在學校的同學們一個建議:如果條件允許的話儘量去參加一些比賽,可能你的技術並不太好,你的內心還很猶豫自己是不是具備參加比賽的能力,但是我還是推薦你去嘗試一下。

爲什麼呢?一個比賽的準備時間,說長點就是 5 ~ 6 個月,說短點也就是 2 ~ 3 個月。在參加這個比賽之前,比賽用到的很多技術你可能沒有實際應用過,甚至連聽都沒有聽過。但是這幾個月的時間應該足夠讓你去學習了,如果你的態度好並且自學能力不差的話一般是沒有問題的。

到了最後,你可能並沒有收穫到一個優秀的名次,但是我覺得參加比賽的經歷對你的幫助纔是最大的。如果後面你還會參加其他比賽的話,我覺得你一定會做的越來越好。

除了比賽,實際項目對自己的個人能力提升與鍛鍊也是非常大的。

多去實踐,將學到的東西運用到實際項目中去。很多人都找我抱怨過沒有實際項目讓自己去做。下面我會介紹到幾種讓你可以有項目經驗的方式,項目經驗對於技術能力的提升和麪試都是很重要的。

想要提高個人硬實力,那麼學習一門新技術的方法一定是至關重要了。


一定要有自己的技術優勢,可能你懂得不是最多的,但是別人不會的你卻會,那麼你就是厲害的!

四丶寫簡歷的時候項目經驗這欄,怎麼纔有項目經驗

如果實在沒有實際項目讓你去做,我覺得你可以通過下面幾種方式:

1.在網上找一個符合自己能力與找工作需求的實戰項目視頻或者博客跟着老師一起做。做的過程中,你要有自己的思考,不要淺嘗輒止,對於很多知識點,別人的講解可能只是滿足項目就夠了,你自己想多點知識的話,對於重要的知識點就要自己學會去往深出學。
2.Github或者碼雲上面有很多實戰類別項目,你可以選擇一個來研究,爲了讓自己對這個項目更加理解,在理解原有代碼的基礎上,你可以對原有項目進行改進或者增加功能。
3.自己動手去做一個自己想完成的東西,遇到不會的東西就臨時去學,現學現賣。

簡歷

華爲Android開發工程師

阿里

公司到底想要什麼樣的人才?
**個人方面:**人品好,與公司以及團隊文化契合,學習能力不錯,抗壓;
能力方面: 能力與你要應聘的崗位所匹配(很多時候不要認爲自己能力很強公司就會招聘你,這意味着公司可能會花更多的錢聘用你。如果你的能力達不到的話,公司一般還會考慮你的潛力如何);

面試注意:

1.提前準備好自我介紹
2.提前準備技術面試
3.面試之前做好定向複習
4.面試覆盤
5.提前知道有哪些技術問題常問,以及非技術問題

五丶面試,刷題

1.Glide的緩存機制

Glide的緩存機制,主要分爲2種緩存,一種是內存緩存,一種是磁盤緩存。

使用內存緩存的原因是: 防止應用重複將圖片讀入到內存,造成內存資源浪費。

使用磁盤緩存的原因是: 防止應用重複的從網絡或者其他地方下載和讀取數據。

具體來講,緩存分爲加載和存儲:

  • 當加載一張圖片的時候,獲取順序:Lru算法緩存-》弱引用緩存-》磁盤緩存(如果設置了的話)。
    當想要加載某張圖片時,先去LruCache中尋找圖片,如果LruCache中有,則直接取出來使用,並將該圖片放入WeakReference中,如果LruCache中沒有,則去WeakReference中尋找,如果WeakReference中有,則從WeakReference中取出圖片使用,如果WeakReference中也沒有圖片,則從磁盤緩存/網絡中加載圖片。
  • 將緩存圖片的時候,寫入順序:弱引用緩存-》Lru算法緩存-》磁盤緩存中。當圖片不存在的時候,先從網絡下載圖片,然後將圖片存入弱引用中,glide會採用一個acquired(int)變量用來記錄圖片被引用的次數, 當acquired變量大於0的時候,說明圖片正在使用中,也就是將圖片放到弱引用緩存當中;如果acquired變量等於0了,說明圖片已經不再被使用了,那麼此時會調用方法來釋放資源,首先會將緩存圖片從弱引用中移除,然後再將它put到LruResourceCache當中。這樣也就實現了正在使用中的圖片使用弱引用來進行緩存,不在使用中的圖片使用LruCache來進行緩存的功能。

另: 從Glide4.x開始,讀取圖片的順序有所改變:弱引用緩存-》Lru算法緩存-》磁盤緩存

2.ThreadLocal的使用場景?與Synchronized相比有什麼特性?

ThreadLocalSynchronized雖然都和多線程有關.
但是ThreadLocal是爲了多線程時,每個線程對變量的獨立訪問.線程間該變量值互不影響.內部是由一個ThreadLocalMap,key爲當前線程的弱引用,value爲變量值.

Synchronized則是另一個意思.多線程時通過同步鎖實現多個線程同時只能有一個線程對變量/方法訪問.

3.Kotlin中集合遍歷有哪幾種方式?

for,foreach,while,do while,遞歸,還有集合的高階方法

4.對於GIF 圖片加載有什麼思路和建議

gif圖實際上就是多幀合併的圖

參考Fresco內部實現:

  • View層使用一個Drawable,包含bitmap,並依據gif的信息不斷的更新並繪製bitmap
  • C層提供api功能,例如:輸入gif數據流,提供解析gif信息、更新bitmap等功能
5.爲什麼說Http是可靠的數據傳輸協議

HTTP是屬於應用層的協議,TCP(傳輸控制協議)和UDP(用戶數據報協議)是屬於傳輸層的協議。

我們都知道TCP協議是面向連接的,每次進行連接都要進行三次握手和四次揮手,所以它的連接是可靠的。而HTTP是在TCP上層的協議,所以它也是可靠的。

那爲什麼TCP可靠?
首先來講一下網絡的分層,因特網協議可以分爲五層,分別是:

應用層->傳輸層->網絡互聯層->網絡訪問層->物理層

或許你覺得很抽象,但是通過栗子你就會發現並沒有那麼複雜
如訪問一個Http請求:

怎麼訪問到這個網站呢?首先我們需要通過網絡,可能是移動網或者寬帶網等(這就是物理層,它是一個傳輸介質),然後找到對應那一臺被我們訪問的服務器的mac地址(網絡訪問層)進行連接,再匹配它的IP(網絡互聯層)是否對應,確定了主機後,再通過端口號9090(傳輸層)訪問對應的進程,由於一個進程裏面有很多業務模塊,而我們需要訪問main模塊(應用層),最終通過不同層來實現網站的訪問。

每個層都是相互獨立,並且向下依賴,而傳輸層是能確定唯一主機的,因爲我們可以通過mac地址、host和端口來確定唯一的一臺訪問主機上面的進程。或許有的人會問,那如果網絡中斷呢?那不就不可靠了嗎,我們常說的網絡中斷是屬於物理層,由於是向下依賴,傳輸層的建立是依賴於下面的三層(網絡互聯層、網絡訪問層、物理層)已經連接成功,如果下面的層都沒有連接成功,也就沒有傳輸層這一說了,所以傳輸層協議是一個“靠譜”的協議。

我們通過分層瞭解了傳輸層是“靠譜”的協議,那麼怎麼保證它是可靠的呢?

那就要講到三次握手和四次揮手的作用了。

三次握手就是在建立連接之前需要客戶端需要先給服務端發出SYN©報文,當服務器收到後需要返回客戶端ACK=SYN©+1,並且傳輸自己生成的SYN(s)給客戶端,客戶端收到後進入已連接狀態,需要再回一個ACK=SYN(s)+1給服務器,服務器收到ACK後也進入了連接狀態,這就是一個三次握手的過程,通過雙方進行三次通信保證此時雙方都已經進入準備狀態。

四次揮手就是在結束連接的時候,客戶端會發送FIN©給服務器,服務器收到後回覆客戶端ACK=FIN©+1告知客戶端收到客戶端的結束請求了,這時客戶端就會進入CLOSING(半關閉狀態),等待服務器的結束請求。 在一段小延遲時間後,服務器也會發送一個FIN(s)請求給客戶端,客戶端收到後發送ACK=FIN(s)+1給服務器,服務器收到ACK後就進入技術狀態。客戶端在等待2個MSL(避免服務器收不到ACK)後也進入結束狀態。

在每次進行連接和斷開連接都需要經過複雜的三次握手和四次握手,從而保證了每個連接都是可靠的,所以TCP協議是可靠的,而HTTP就是TCP上層的協議,所有連接都是基於TCP協議的。

在我們能夠確定每個請求對應的唯一主機和端口號,並且通過Http協議添加響應的請求數據信息(如模塊名字等)確定請求的代碼位置,並且在每次請求都通過三次握手和四次揮手保證連接的可靠性,所以一個Http請求是可靠的。

在我們能夠確定每個請求對應的唯一主機和端口號,並且通過Http協議添加響應的請求數據信息(如模塊名字等)確定請求的代碼位置,並且在每次請求都通過三次握手和四次揮手保證連接的可靠性,所以一個Http請求是可靠的。

6.如何繞過Android9.0針對反射的限制

雙重反射,即利用反射調用反射API,這個時候系統進行棧回溯,發現直接調用者是反射API,反射API也是系統API,就直接通過了

7.談一談Activity,View,Window三者的關係

在activity中調用attach,創建window;

創建的window是其子類phonewindow,在attach中創建phonewindow;

在activity中調用setcontentview(R.layout.xx);其實就是調用getwindow.setcontentview()

創建parentview;將指定的R.layout.xx佈局進行填充

調用viewgroup,調用viewGroup先移除removeAllview();在進行添加新的view --addview().

8.如何進行單元測試的?以及如何應用在MVP和MVVM中?

單元測試庫 junit mockito Rebolectric

說下mvp工程中的測試方法 測試主要有 三大部分

1. 普通工具類 使用junit 直接測試
2. mvp的p 使用 @mock標註view的接口, 初始化真正的p, 直接調用p的方法 看看 verify view的某些方法是否按照預期被調用
3. mvp的v 用rebolectric去setup 一個Activity, 然後 用這個庫找到 界面上的按鈕,或者觸發生命週期(onstart),判斷一下當前界面的某些view是否被顯示 或者 textview的值或者 dialog 是否顯示 toast是否彈出錯誤
4. 還有網絡部分的測試,可以直接使用junit進行測試 判斷下返回值是否符合預期

9.請說說依賴注入框架ButterKnife的實現原理?
  • 通過註解器在編譯期間生成一個XX_ViewBinding.java文件(XX可以是activity,fragment,adapter,dialog),這個文件這麼生成的?
    註解器裏會添加需要類型的註解;查找XX類中的特定類型註解,如果有,拼接成字符串,創建並寫到XX_ViewBinding.java文件中
  • XX_ViewBinding.java會持有XX的引用,如果是初始化控件,通過xx.findViewById實現,如果是設置監聽,類似xx.setOnClickListener實現
  • XX類中初始化XX_ViewBinding對象,這樣打通了整個流程
10.談一談屏幕刷新機制

屏幕刷新頻率和繪製頻率

cpu 負責 measure layout draw => displayList

gpu 負責 display => 位圖

每個16ms會發送一次垂直同步信號 vsync

每次信號發送的時候都會從gpu的buffer中取出渲染好的位圖 顯示在屏幕上

同時如果有需要 還會進行下一次的 cpu計算,計算好後放入buffer中

如果計算時間超過了兩次vsync之間的時間 即16ms 則 vsync信號會把 上一次gpu buffer中的信息展示出來 這時候就是卡頓

另外如果頁面沒有變化 屏幕還是一樣會去buffer中取出上一次的刷新,只不過cpu不再去計算而已

11.說說Kotlin中的Any與Java中的Object有何異同?

同:

  • 都是頂級父類

異:

  • 成員方法不同
    Any只聲明瞭toString()hashCode()equals()作爲成員方法。

我們思考下,爲什麼 Kotlin 設計了一個 Any ?

當我們需要和 Java 互操作的時候,Kotlin 把 Java 方法參數和返回類型中用到的 Object 類型看作 Any,這個 Any 的設計是 Kotlin 兼容 Java 時的一種權衡設計。

所有 Java 引用類型在 Kotlin 中都表現爲平臺類型。當在 Kotlin 中處理平臺類型的值的時候,它既可以被當做可空類型來處理,也可以被當做非空類型來操作。

試想下,如果所有來自 Java 的值都被看成非空,那麼就容易寫出比較危險的代碼。反之,如果 Java 值都強制當做可空,則會導致大量的 null 檢查。綜合考量,平臺類型是一種折中的設計方案。

12.談一談java線程安全的集合有哪些

1.早期的線程安全集合

  • Vector
    = 全部方法加 synchronized 的 ArrayList
  • HashTable
    = 全部方法加 synchronized 的 HashMap

2.包裝工具類

  • Collections.synchronizedXXX()
    在原集合的基礎上添加了鎖對象,集合中的每個方法都通過這個鎖對象實現同步

3.java.util.concurrent包

  • ConcurrentHashMap
    1.7 分段鎖技術,1.8 對table每行首元素加鎖
  • CopyOnWriteXXXX
    加了寫鎖,寫的時候鎖住的整個對象,讀則可以併發執行

4.其他

  • Stack
    繼承了 Vector
13.請談談如何加載Bitmap並防止內存溢出

首先我們 要知道bitmap內存是怎麼計算的例子:

手機屏幕大小 1080 x 1920(inTarget = 420),加載 xhdpi (inDensity = 320)中的圖片 1920 x 1080,scale = 420 / 320,
最總我們可以得知 他的佔用內存 1418 * 2520 * 4
很明顯 被放大了。

防止內存溢出:

1.對圖片進行內存壓縮;
2.高分辨率的圖片放入對應文件夾;
3.內存複用
4.及時回收

關於我

更多面試內容分析,分享,學習筆記整理,視頻整理

https://github.com/xiangjiana/Android-MS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章