前言

金三銀四到來了,找工作的好時候到了,小夥伴們是不是都在忙著找工作呢,小弟前一陣也是忙著在找工作,面試了好多公司,所幸的是進到了自己心儀的公司,也是很幸運的。下面我將自己親身實戰的面試題及收到的面試題總結並分享答案出來。歡迎各位大哥指導、指點。

下面這些只是Android方面的知識,如果有需要Java方面的面試題的話,可以在下面留言。

PS:末尾有送給大家的小福利

1.Activity生命週期(這個是必問的)

onCreate()創建活動,做一些數據初始化操作

onStart()由不可見變為可見

onResume()可以與用戶進行交互,位於棧頂

onPause()暫停,啟動或恢復另一個活動時調用

onStop()停止,變為不可見

onDestroy() 銷毀

onRestart()由停止狀態變為運行狀態

2.Fragment生命週期 (這個有可能會問到,問的機率不是很大)

3.Service生命週期

onCreate()

首次創建服務時,系統將調用此方法。如果服務已在運行,則不會調用此方法,該方法只調用一次。

onStartCommand()

當另一個組件通過調用startService()請求啟動服務時,系統將調用此方法。

onDestroy()

當服務不再使用且將被銷毀時,系統將調用此方法。

onBind()

當另一個組件通過調用bindService()與服務綁定時,系統將調用此方法。

onUnbind()

當另一個組件通過調用unbindService()與服務解綁時,系統將調用此方法。

onRebind()

當舊的組件與服務解綁後,另一個新的組件與服務綁定,onUnbind()返回true時,系統將調用此方法。

4.Service啟動方式(問到Service,這個肯定是要問到的)

1.startService

①.定義一個類繼承service

②.在manifest.xml文件中配置該service

③.使用context的startService(intent)啟動該service

④.不再使用時,調用stopService(Intent)停止該服務

2.bindService

①.創建bindService服務段,繼承自service並在類中,創建一個實現binder介面的實例對象並提供公共方法給客戶端調用

②.從onbind()回調方法返回此binder實例

③.在客戶端中,從onserviceconnected()回調方法接收binder,並使用提供的方法調用綁定服務

5.Activity的啟動方式(偶爾會問)

①.standard模式

a.Activity的默認啟動模式

b.每啟動一個Activity就會在棧頂創建一個新的實例。例如:鬧鐘程序

缺點:當Activity已經位於棧頂時,而再次啟動Activity時還需要在創建一個新的實例,不能直接復用。

②.singleTop模式

特點:該模式會判斷要啟動的Activity實例是否位於棧頂,如果位於棧頂直接復用,否則創建新的實例。 例如:瀏覽器的書籤

?缺點:如果Activity並未處於棧頂位置,則可能還會創建多個實例。

③.singleTask模式

特點:使Activity在整個應用程序中只有一個實例。每次啟動Activity時系統首先檢查棧中是否存在當前Activity實例,如果存在

則直接復用,並把當前Activity之上所有實例全部出棧。例如:瀏覽器主界面

④.singleInstance模式

特點:該模式的Activity會啟動一個新的任務棧來管理Activity實例,並且該勢力在整個系統中只有一個。無論從那個任務棧中啟動該Activity,都會是該Activity所在的任務棧轉移到前臺,從而使Activity顯示。主要作用是為了在不同程序中共享一個Activity

6.Touch事件傳遞機制

在我們點擊屏幕時,會有下列事件發生:

Activity調用dispathTouchEvent()方法,把事件傳遞給Window;

Window再將事件交給DecorView(DecorView是View的根佈局);

DecorView再傳遞給ViewGroup;

Activity ——> Window ——> DecorView ——> ViewGroup——> View

事件分發的主要有三個關鍵方法

dispatchTouchEvent() 分發

onInterceptTouchEvent() 攔截 ,只有ViewGroup獨有此方法

onTouchEvent() 處理觸摸事件

Activity首先調用dispathTouchEvent()進行分發,接著調用super向下傳遞

ViewGroup首先調用dispathTouchEvent()進行分發,接著會調用onInterceptTouchEvent()(攔截事件)。若攔截事件返回為true,表示攔截,事件不會向下層的ViewGroup或者View傳遞;false,表示不攔截,繼續分發事件。默認是false,需要提醒一下,View是沒有onInterceptTouchEvent()方法的

事件在ViewGroup和ViewGroup、ViewGroup和View之間進行傳遞,最終到達View;

View調用dispathTouchEvent()方法,然後在OnTouchEvent()進行處理事件;OnTouchEvent() 返回true,表示消耗此事件,不再向下傳遞;返回false,表示不消耗事件,交回上層處理。

7.介紹下實現一個自定義View的基本流程

①.自定義View的屬性 編寫attr.xml文件

②.在layout佈局文件中引用,同時引用命名空間

③.在View的構造方法中獲得我們自定義的屬性 ,在自定義控制項中進行讀取(構造方法拿到attr.xml文件值)

④.重寫onMesure

⑥.重寫onDraw

8.Android中的動畫有哪些

逐幀動畫(Frame Animation)

載入一系列Drawable資源來創建動畫,簡單來說就是播放一系列的圖片來實現動畫效果,可以自定義每張圖片的持續時間

補間動畫(Tween Animation)

Tween可以對View對象實現一系列動畫效果,比如平移,縮放,旋轉,透明度等。但是它並不會改變View屬性的值,只是改變了View的繪製的位置,比如,一個按鈕在動畫過後,不在原來的位置,但是觸發點擊事件的仍然是原來的坐標。

屬性動畫(Property Animation)

動畫的對象除了傳統的View對象,還可以是Object對象,動畫結束後,Object對象的屬性值被實實在在的改變了

9.ANR是什麼?怎樣避免和解決ANR

Application Not Responding,即應用無響應

出現的原因有三種:

a)KeyDispatchTimeout(5 seconds)主要類型按鍵或觸摸事件在特定時間內無響應

b)BroadcastTimeout(10 seconds)BoradcastReceiver在特定的時間內無法處理

c)ServiceTimeout(20 seconds)小概率類型Service在特定的時間內無法處理完成

避免ANR最核心的一點就是在主線程減少耗時操作。通常需要從那個以下幾個方案下手:

a)使用子線程處理耗時IO操作

b)降低子線程優先順序,使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先順序,否則仍然會降低程序響應,因為默認Thread的優先順序和主線程相同

c)使用Handler處理子線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程

d)Activity的onCreate和onResume回調中盡量避免耗時的代碼

e)BroadcastReceiver中onReceiver代碼也要盡量減少耗時操作,建議使用intentService處理。intentService是一個非同步的,會自動停止的服務,很好解決了傳統的Service中處理完耗時操作忘記停止並銷毀Service的問題

10.如何優化ListView(偶爾會問)

①Item佈局,層級越少越好,使用hierarchyview工具查看優化。

②復用convertView

③使用ViewHolder

④item中有圖片時,非同步載入

⑤快速滑動時,不載入圖片

⑥item中有圖片時,應對圖片進行適當壓縮

⑦實現數據的分頁載入

11.設備橫豎屏切換的時候,生面週期的變化(這個偶爾會問)

不設置Activity的android:configChanges時,切屏會重新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次

設置Activity的android:configChanges=」orientation」時,切屏還是會重新調用各個生命週期,切橫、豎屏時只會執行一次

設置Activity的android:configChanges=」orientation|keyboardHidden」時,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged方法

12.AndroidUI的適配

字體使用sp,使用dp,多使用match_parent,wrap_content,weight

圖片資源,不同圖片的的解析度,放在相應的文件夾下可使用百分比代替。

13.RecyclerView和ListView的區別(這個是必問的)

RecyclerView可以完成ListView,GridView的效果,還可以完成瀑布流的效果。同時還可以設置列表的滾動方向(垂直或者水平);

RecyclerView中view的復用不需要開發者自己寫代碼,系統已經幫封裝完成了。

RecyclerView可以進行局部刷新。

RecyclerView提供了API來實現item的動畫效果。

在性能上:

如果需要頻繁的刷新數據,需要添加動畫,則RecyclerView有較大的優勢。

如果只是作為列表展示,則兩者區別並不是很大。

14,Android非同步消息處理機制(這個也會經常問到)

非同步消息處理機制主要是用來解決子線程更新UI的問題

主要有四個部分:

①. Message (消息)中

在線程之間傳遞,可在內部攜帶少量信息,用於不同線程之間交換數據

可以使用what、arg1、arg2欄位攜帶整型數據

obj欄位攜帶Object對象

②. Handler (處理者)

主要用於發送和處理消息,sendMessage()用來發送消息,最終會回到handleMessage()進行處理

③. MessageQueue (消息隊列)

主要存放所有通過Handler發送的消息,它們會一直存在於隊列中等待被處理

每個線程只有一個MessageQueue

④. Looper (循環器)

調用loop()方法後,會不斷從MessageQueue 取出待處理的消息,然後傳遞到handleMessage進行處理

15.內存泄漏和內存溢出是什麼?一般怎麼處理內存泄漏?

(1)內存溢出(OOM)和內存泄露(對象無法被回收)的區別。

(2)引起內存泄露的原因

(3)內存泄露檢測工具 ------>LeakCanary

內存溢出 out of memory:是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。內存溢出通俗的講就是內存不夠用。

內存泄露 memory leak:是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光

內存泄露原因以及解決:

一、Handler 引起的內存泄漏。

解決:將Handler聲明為靜態內部類,就不會持有外部類SecondActivity的引用,其生命週期就和外部類無關,

如果Handler裡面需要context的話,可以通過弱引用方式引用外部類

二、單例模式引起的內存泄漏。

解決:Context是ApplicationContext,由於ApplicationContext的生命週期是和app一致的,不會導致內存泄漏

三、非靜態內部類創建靜態實例引起的內存泄漏。

解決:把內部類修改為靜態的就可以避免內存泄漏了

四、非靜態匿名內部類引起的內存泄漏。

解決:將匿名內部類設置為靜態的。

五、註冊/反註冊未成對使用引起的內存泄漏。

註冊廣播接受器、EventBus等,記得解綁。

六、資源對象沒有關閉引起的內存泄漏。

在這些資源不使用的時候,記得調用相應的類似close()、destroy()、recycler()、release()等方法釋放。

七、集合對象沒有及時清理引起的內存泄漏。

通常會把一些對象裝入到集合中,當不使用的時候一定要記得及時清理集合,讓相關對象不再被引用。

16.圖片載入框架有哪些?他們之間的區別是什麼?(這個也是必問的)

ImageLoader :

優點:

①支持下載進度監聽;

②可以在 View 滾動中暫停圖片載入;

③默認實現多種內存緩存演算法這幾個圖片緩存都可以配置緩存演算法,不過 ImageLoader 默認實現了較多緩存演算法,如 Size 最大先刪除、使用最少先刪除、最近最少使用、先進先刪除、時間最長先刪除等;

④支持本地緩存文件名規則定義;

缺點:

缺點在於不支持GIF圖片載入, 緩存機制沒有和http的緩存很好的結合, 完全是自己的一套緩存機制

Picasso:

優點:

①自帶統計監控功能,支持圖片緩存使用的監控,包括緩存命中率、已使用內存大小、節省的流量等。

②支持優先順序處理

③支持延遲到圖片尺寸計算完成載入

④支持飛行模式、並發線程數根據網路類型而變,手機切換到飛行模式或網路類型變換時會自動調整線程池最大並發數。

⑤ 「無」本地緩存。Picasso 自己沒有實現本地緩存,而由okhttp 去實現,這樣的好處是可以通過請求 Response Header 中的 Cache-Control 及 Expired 控制圖片的過期時間。

缺點:

於不支持GIF,默認使用ARGB_8888格式緩存圖片,緩存體積大。

Glide:

優點:

①圖片緩存->媒體緩存 ,支持 Gif、WebP、縮略圖。甚至是 Video。

②支持優先順序處理

③與 Activity/Fragment 生命週期一致,支持 trimMemory

④支持 okhttp、Volley。Glide 默認通過 UrlConnection 獲取數據,可以配合 okhttp 或是 Volley 使用。實際 ImageLoader、Picasso 也都支持 okhttp、Volley。

⑤內存友好,內存緩存更小圖片,圖片默認使用默認 RGB565 而不是 ARGB888

缺點:

清晰度差,但可以設置

Fresco:

優點:

①圖片存儲在安卓系統的匿名共享內存, 而不是虛擬機的堆內存中,所以不會因為圖片載入而導致oom, 同時也減少垃圾回收器頻繁調用回收Bitmap導致的界面卡頓,性能更高.

②漸進式載入JPEG圖片, 支持圖片從模糊到清晰載入

③圖片可以以任意的中心點顯示在ImageView, 而不僅僅是圖片的中心.

④ JPEG圖片改變大小也是在native進行的, 不是在虛擬機的堆內存, 同樣減少OOM

⑤很好的支持GIF圖片的顯示

缺點:

框架較大, 影響Apk體積,使用較繁瑣

17.網路框架有哪些?他們之間的區別是什麼?(這個也會問到)

Xutils

這個框架非常全面,可以進行網路請求,可以進行圖片載入處理,可以數據儲存,還可以對view進行註解,使用這個框架非常方便,但是缺點也是非常明顯的,使用這個項目,會導致項目對這個框架依賴非常的嚴重,一旦這個框架出現問題,那麼對項目來說影響非常大的

OKhttp

Android開發中是可以直接使用現成的api進行網路請求的。就是使用HttpClient,HttpUrlConnection進行操作。okhttp針對Java和Android程序,封裝的一個高性能的http請求庫,支持同步,非同步,而且okhttp又封裝了線程池,封裝了數據轉換,封裝了參數的使用,錯誤處理等。API使用起來更加的方便。但是我們在項目中使用的時候仍然需要自己在做一層封裝,這樣才能使用的更加的順手。

Volley

Volley是Google官方出的一套小而巧的非同步請求庫,該框架封裝的擴展性很強,支持HttpClient、HttpUrlConnection, 甚至支持OkHttp,而且Volley裡面也封裝了ImageLoader,所以如果你願意你甚至不需要使用圖片載入框架,不過這塊功能沒有一些專門的圖片載入框架強大,對於簡單的需求可以使用,稍複雜點的需求還是需要用到專門的圖片載入框架。Volley也有缺陷,比如不支持post大數據,所以不適合上傳文件。不過Volley設計的初衷本身也就是為頻繁的、數據量小的網路請求而生。

Retrofit

Retrofit是Square公司出品的默認基於OkHttp封裝的一套RESTful網路請求框架,RESTful是目前流行的一套api設計的風格, 並不是標準。Retrofit的封裝可以說是很強大,裡面涉及到一堆的設計模式,可以通過註解直接配置請求,可以使用不同的http客戶端,雖然默認是用http ,可以使用不同Json Converter 來序列化數據,同時提供對RxJava的支持,使用Retrofit + OkHttp + RxJava + Dagger2 可以說是目前比較潮的一套框架,但是需要有比較高的門檻。

Volley VS OkHttp

Volley的優勢在於封裝的更好,而使用OkHttp你需要有足夠的能力再進行一次封裝。而OkHttp的優勢在於性能更高,因為 OkHttp基於NIO和Okio ,所以性能上要比 Volley更快。IO 和 NIO這兩個都是Java中的概念,如果我從硬碟讀取數據,第一種方式就是程序一直等,數據讀完後才能繼續操作這種是最簡單的也叫阻塞式IO,還有一種是你讀你的,程序接著往下執行,等數據處理完你再來通知我,然後再處理回調。而第二種就是 NIO 的方式,非阻塞式, 所以NIO當然要比IO的性能要好了,而 Okio是 Square 公司基於IO和NIO基礎上做的一個更簡單、高效處理數據流的一個庫。理論上如果Volley和OkHttp對比的話,更傾向於使用 Volley,因為Volley內部同樣支持使用OkHttp,這點OkHttp的性能優勢就沒了, 而且 Volley 本身封裝的也更易用,擴展性更好些。

OkHttp VS Retrofit

毫無疑問,Retrofit 默認是基於 OkHttp 而做的封裝,這點來說沒有可比性,肯定首選 Retrofit。

Volley VS Retrofit

這兩個庫都做了不錯的封裝,但Retrofit解耦的更徹底,尤其Retrofit2.0出來,Jake對之前1.0設計不合理的地方做了大量重構, 職責更細分,而且Retrofit默認使用OkHttp,性能上也要比Volley佔優勢,再有如果你的項目如果採用了RxJava ,那更該使用 Retrofit 。所以這兩個庫相比,Retrofit更有優勢,在能掌握兩個框架的前提下該優先使用 Retrofit。但是Retrofit門檻要比Volley稍高些,要理解他的原理,各種用法,想徹底搞明白還是需要花些功夫的,如果你對它一知半解,那還是建議在商業項目使用Volley吧。

18.熟悉哪些設計模式?

按照自己的實際情況回答,當然是越多越好。比如我自己也就熟悉個單例模式。

19.三級緩存(這個偶爾會問)

網路載入,不優先載入,速度慢,浪費流量

本地緩存,次優先載入,速度快

內存緩存,優先載入,速度最快

首次載入Android App時,肯定要通過網路交互來獲取圖片,之後我們可以將圖片保存至本地SD卡和內存中,之後運行APP時,優先訪問內存中的圖片緩存,若內存中沒有,則載入本地SD卡中圖片,最後選擇訪問網路

20.Android與伺服器交互的方式中的對稱加密和非對稱加密是什麼?

對稱加密,就是加密和解密數據都是使用同一個key,這方面的演算法有DES。

非對稱加密,加密和解密是使用不同的key。發送數據之前要先和服務端約定生成公鑰和私鑰,使用公鑰加密的數據可以用私鑰解密,反之。這方面的演算法有RSA。ssh 和 ssl都是典型的非對稱加密。

關於我的Android學習之路

不知不覺自己已經做了幾年開發了,由記得剛出來工作的時候感覺自己能牛逼,現在回想起來感覺好無知。懂的越多的時候你才會發現懂的越少。

如果你的知識是一個圓,當你的圓越大時,圓所接觸到的外面的世界也就越大。

在我學習的過程中,最開始是在網上找了很多資料,畢竟這些資料是我們開始最快速的學習方法,這裡我放上我這些年在網上收集到的資料,然後再以我的工作經驗給大家總結一下,讓你們少走些彎路,提取一些目前互聯網公司最主流的Android開發架構技術,希望能幫助到大家!

Java語言進階與Android相關技術內核

Android應用是由Java語言進行開發的,SDK也是由Java語言編寫,對於Android來說,只要SDK沒有用Kotlin重寫,那麼Java語言是都需要學習的。而且Android APK的後臺伺服器程序大概率是Java語言構建,所以掌握Java也是一種必然,這就是為什麼BAT面試為什麼死摳你的Java水平。

APP開發框架體系

APP開發這塊知識是現今使用者最多的,並且大多都是CV工程師,程序員界的2-8定律:80%的問題只需要使用20%的知識就可以解決,Android開發也不例外。因而,我們大部分人已經逐步變成了代碼搬運工而自己卻不知道。代碼容易搬運,架構體系卻難以複製,要成為架構師,你必須自己親自去項目實戰,讀源碼,研究原理。

移動架構師專題項目實戰

架構師不是天生的,是在項目中磨練起來的,所以,我們學了技術就需要結合項目進行實戰訓練,那麼在Android裡面最常用的架構無外乎 MVC,MVP,MVVM,但是這些思想如果和模塊化,層次化,組件化混和在一起,那就不是一件那麼簡單的事了,我們需要一個真正身經百戰的架構師才能講解透徹其中蘊含的深理。

Android高級架構技術;如何系統化學習?

全套體系化高級架構視頻;七大主流技術模塊,視頻+源碼+筆記

設計面試和數據結構演算法專題;大廠必會,鞏固基礎

最後

如果你看到了這裡,覺得文章寫得不錯就給個讚唄?如果你覺得那裡值得改進的,請給我留言。一定會認真查詢,修正不足。謝謝。

最後針對Android程序員,除了上面的知識體系,我這邊給大家整理了一些資料,其中分享內容包括不限於高級UI、性能優化、移動架構師、NDK、混合式開發(ReactNative+Weex)微信小程序、Flutter等全方面的Android進階實踐技術;希望能幫助到大家,也節省大家在網上搜索資料的時間來學習,也可以分享動態給身邊好友一起學習!關注我和我的專欄~

為什麼某些人會一直比你優秀,是因為他本身就很優秀還一直在持續努力變得更優秀,而你是不是還在滿足於現狀內心在竊喜!希望讀到這的您能轉發分享點個小贊+關注,以後還會更新技術乾貨,謝謝您的支持!

Android架構師之路很漫長,一起共勉吧!


推薦閱讀:
相關文章