想進BAT嗎?點擊上方的藍色文字關注我們后,馬上 告訴你答案!!
歡迎收藏和專注本文,以后我們會陸續的整理和收集其他的公司的面試題,擴大我們的面試庫,形成專欄。
這是由樂視網工程師整理的一份一線互聯網公司面試題。來自於百度、小米、樂視、美團、58、獵豹、360、新浪、搜狐內部題庫。
大家看了后就知道其實一線互聯網公司的面試並沒有你們想象的多么難,很多基礎是共通的。特此整理分享給大家,希望能給最近准備面試的,特別是准備投遞 BAT 等一線互聯網公司的同學一點幫助。再次向原作者致謝。大家也可點擊「閱讀原文」查看。
本面試題機會所有的問題都可以從本公眾號找到答案(點擊左下角的“精品文章->往期回顧” 查看)。熟悉本文中列出的知識點會大大增加通過前兩輪技術面試的幾率。
一、java基礎
1. 接口的意義(百度)
2. 抽象類的意義(樂視)
3. 內部類的作用(百度,樂視)
4. 父類的靜態方法能否被子類重寫,為什么?(獵豹)
5. 舉1-2個排序算法,並使用java代碼實現(美團)
http://blog.csdn.net/xhmj12/article/category/6206216
6. 列舉java的集合和繼承關系(百度、美團)
7. java虛擬機的特性(百度、樂視)
8. 哪些情況下的對象會被垃圾回收機制處理掉(樂視、美團、小米)
9. 進程和線程的區別(獵豹)
10. Java中==和equals的區別,equals和hashCode的區別(樂視)
11. 常見的排序算法時間復雜度(小米)
12. ArrayList和HashMap的實現原理(美團,百度)
13. java 狀態機
http://www.jdon.com/designpatterns/designpattern_State.htm
14. java中int char long各占多少字節數
15. java int與integer的區別
16. string stringbuffer stringbuilder 區別(小米、樂視、百度)
17. Java多態(樂視)
18. 什么導致線程阻塞(58、美團)
19. 抽象類接口區別(360)
20. 容器類之間的區別(樂視、美團)
21. java 內部類(小米)
22. Java中hashmap和hashtable的區別(樂視、小米)
23. ArrayMap VS HashMap
二、android基礎
1.數據庫的操作類型有哪些,如何導入外部數據庫?
把原數據庫包括在項目源碼的 res/raw。android系統下數據庫應該存放在 /data/data/com..(package name)/ 目錄下,所以我們需要做的是把已有的數據庫傳入那個目錄下.操作方法是用FileInputStream讀取原數據庫,再用FileOutputStream把讀取到的東西寫入到那個目錄.
2.是否使用過本地廣播,和全局廣播有什么差別?
因廣播數據在本應用范圍內傳播,不用擔心隱私數據泄露的問題。 不用擔心別的應用偽造廣播,造成安全隱患。 相比在系統內發送全局廣播,它更高效。
3.是否使用過intentServer,作用是什么,AIDL解決了什么問題?(小米)
IntentService——Handler與Service的結合
4.Activity、Window、View三者的差別,fragment的特點?(360)
Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。
在Activity中調用attach,創建了一個Window
創建的window是其子類PhoneWindow,在attach中創建PhoneWindow
在Activity中調用setContentView(R.layout.xxx)
其中實際上是調用的getWindow().setContentView()
調用PhoneWindow中的setContentView方法
創建ParentView:作為ViewGroup的子類,實際是創建的DecorView(作為FramLayout的子類)
將指定的R.layout.xxx進行填充通過布局填充器進行填充【其中的parent指的就是DecorView】
調用到ViewGroup
調用ViewGroup的removeAllView(),先將所有的view移除掉
添加新的view:addView()
fragment 特點
Fragment可以作為Activity界面的一部分組成出現;
可以在一個Activity中同時出現多個Fragment,並且一個Fragment也可以在多個Activity中使用;
在Activity運行過程中,可以添加、移除或者替換Fragment;
Fragment可以響應自己的輸入事件,並且有自己的生命周期,它們的生命周期會受宿主Activity的生命周期影響。
5.描述一次網絡請求的流程(新浪)
6.Handler、Thread和HandlerThread的差別(小米)
從Android中Thread(java.lang.Thread -> java.lang.Object)描述可以看出,Android的Thread沒有對Java的Thread做任何封裝,但是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread做了很多便利Android系統的封裝。
android.os.Handler可以通過Looper對象實例化,並運行於另外的線程中,Android提供了讓Handler運行於其它線程的線程實現,也是就HandlerThread。HandlerThread對象start后可以獲得其Looper對象,並且使用這個Looper對象實例Handler。
7. 低版本SDK實現高版本api(小米)
自己實現或@TargetApi annotation
8. 編譯安卓系統(百度)
1. 創建一個大小寫敏感的磁盤鏡像文件
2. 首先你要安裝的就是Xcode
3. 從macports.org安裝MacPorts工具
4. 從MacPorts安裝make,git, and GPG packages
5. 修改文件標識符限制
6. 創建~/bin/目錄
7. 安裝repo
8. 設置repo可執行權限
9. 修改~/bin/repo文件將第五行
10. 新建目錄gingerbread,並進入該目錄
11. 執行repoinit
12. reposync
13. 設置必要的編譯環境-編譯
14. 利用Eclipse調試代碼
9.launch mode應用場景(百度、小米、樂視)
standard,創建一個新的Activity。
singleTop,棧頂不是該類型的Activity,創建一個新的Activity。否則,onNewIntent。
singleTask,回退棧中沒有該類型的Activity,創建Activity,否則,onNewIntent+ClearTop。
注意: 1.設置了"singleTask"啟動模式的Activity,它在啟動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的Task存在; 如果存在這樣的Task,它就會在這個Task中啟動,否則就會在新的任務棧中啟動。因此, 如果我們想要設置了"singleTask"啟動模式的Activity在新的任務中啟動,就要為它設置一個獨立的taskAffinity屬性值。 2.如果設置了"singleTask"啟動模式的Activity不是在新的任務中啟動時,它會在已有的任務中查看是否已經存在相應的Activity實例, 如果存在,就會把位於這個Activity實例上面的Activity全部結束掉,即最終這個Activity 實例會位於任務的Stack頂端中。 3.在一個任務棧中只有一個”singleTask”啟動模式的Activity存在。他的上面可以有其他的Activity。這點與singleInstance是有區別的。
singleInstance,回退棧中,只有這一個Activity,沒有其他Activity。
singleTop適合接收通知啟動的內容顯示頁面。 例如,某個新聞客戶端的新聞內容頁面,如果收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。 singleTask適合作為程序入口點。 例如瀏覽器的主界面。不管從多少個應用啟動瀏覽器,只會啟動主界面一次,其余情況都會走onNewIntent,並且會清空主界面上面的其他頁面。 singleInstance應用場景:鬧鈴的響鈴界面。 你以前設置了一個鬧鈴:上午6點。在上午5點58分,你啟動了鬧鈴設置界面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天; 在6點時,鬧鈴響了,並且彈出了一個對話框形式的 Activity(名為 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵,回到的是微信的聊天界面,這是因為 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 因此退出之后這個 Task 的棧空了。如果是以 SingleTask 打開 AlarmAlertActivity,那么當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設置界面。
10.touch 事件傳遞流程(小米)
11.view繪制流程(百度)
12.多線程(360)
Activity.runOnUiThread(Runnable)
View.post(Runnable),View.postDelay(Runnable,long)
13.線程同步(百度)
單例:http://blog.csdn.net/xhmj12/article/details/51260470
14.什么情況導致內存泄漏(美團)
描述: 資源性對象比如(Cursor,File文件等)往往都用了一些緩沖,我們在不使用的時候,應該及時關閉它們,以便它們的緩沖及時回收內存。它們的緩沖不僅存在於 java虛擬機內,還存在於java虛擬機外。如果我們僅僅是把它的引用設置為null,而不關閉它們,往往會造成內存泄漏。因為有些資源性對象,比如 SQLiteCursor(在析構函數finalize(),如果我們沒有關閉它,它自己會調close()關閉),如果我們沒有關閉它,系統在回收它時也會關閉它,但是這樣的效率太低了。因此對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,然后才置為null.在我們的程序退出時一定要確保我們的資源性對象已經關閉。 程序中經常會進行查詢數據庫的操作,但是經常會有使用完畢Cursor后沒有關閉的情況。如果我們的查詢結果集比較小,對內存的消耗不容易被發現,只有在常時間大量操作的情況下才會復現內存問題,這樣就會給以后的測試和問題排查帶來困難和風險。
2.構造Adapter時,沒有使用緩存的convertView
描述: 以構造ListView的BaseAdapter為例,在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 來向ListView提供每一個item所需要的view對象。初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化一定數量的 view對象,同時ListView會將這些view對象緩存起來。當向上滾動ListView時,原先位於最上面的list item的view對象會被回收,然后被用來構造新出現的最下面的list item。這個構造過程就是由getView()方法完成的,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。由此可以看出,如果我們不去使用 convertView,而是每次都在getView()中重新實例化一個View對象的話,即浪費資源也浪費時間,也會使得內存占用越來越大。 ListView回收list item的view對象的過程可以查看: android.widget.AbsListView.java --> voidaddScrapView(View scrap) 方法。 示例代碼:
3.Bitmap對象不在使用時調用recycle()釋放內存
4.試着使用關於application的context來替代和activity相關的context
這是一個很隱晦的內存泄漏的情況。有一種簡單的方法來避免context相關的內存泄漏。最顯著地一個是避免context逃出他自己的范圍之外。使用Application context。這個context的生存周期和你的應用的生存周期一樣長,而不是取決於activity的生存周期。如果你想保持一個長期生存的對象,並且這個對象需要一個context,記得使用application對象。你可以通過調用 Context.getApplicationContext() or Activity.getApplication()來獲得。更多的請看這篇文章如何避免 Android內存泄漏。
5.注冊沒取消造成的內存泄漏
一些Android程序可能引用我們的Anroid程序的對象(比如注冊機制)。即使我們的Android程序已經結束了,但是別的引用程序仍然還有對我們的Android程序的某個對象的引用,泄漏的內存依然不能被垃圾回收。調用registerReceiver后未調用unregisterReceiver。 比如:假設我們希望在鎖屏界面(LockScreen)中,監聽系統中的電話服務以獲取一些信息(如信號強度等),則可以在LockScreen中定義一個 PhoneStateListener的對象,同時將它注冊到TelephonyManager服務中。對於LockScreen對象,當需要顯示鎖屏界面的時候就會創建一個LockScreen對象,而當鎖屏界面消失的時候LockScreen對象就會被釋放掉。 但是如果在釋放 LockScreen對象的時候忘記取消我們之前注冊的PhoneStateListener對象,則會導致LockScreen無法被垃圾回收。如果不斷的使鎖屏界面顯示和消失,則最終會由於大量的LockScreen對象沒有辦法被回收而引起OutOfMemory,使得system_process 進程掛掉。 雖然有些系統程序,它本身好像是可以自動取消注冊的(當然不及時),但是我們還是應該在我們的程序中明確的取消注冊,程序結束時應該把所有的注冊都取消掉。
6.集合中對象沒清理造成的內存泄漏
我們通常把一些對象的引用加入到了集合中,當我們不需要該對象時,並沒有把它的引用從集合中清理掉,這樣這個集合就會越來越大。如果這個集合是static的話,那情況就更嚴重了。
15.ANR定位和修正
如果開發機器上出現問題,我們可以通過查看/data/anr/traces.txt即可,最新的ANR信息在最開始部分。
主線程被IO操作(從4.0之后網絡IO不允許在主線程中)阻塞。
主線程中存在耗時的計算
主線程中錯誤的操作,比如Thread.wait或者Thread.sleep等 Android系統會監控程序的響應狀況,一旦出現下面兩種情況,則彈出ANR對話框
應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸)
BroadcastReceiver未在10秒內完成相關的處理
Service在特定的時間內無法處理完成 20秒
使用AsyncTask處理耗時IO操作。
使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,否則仍然會降低程序響應,因為默認Thread的優先級和主線程相同。
使用Handler處理工作線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。
Activity的onCreate和onResume回調中盡量避免耗時的代碼
BroadcastReceiver中onReceive代碼也要盡量減少耗時,建議使用IntentService處理。
16.什么情況導致oom(樂視、美團)
使用更加輕量的數據結構
Android里面使用Enum
Bitmap對象的內存占用
更大的圖片
onDraw方法里面執行對象的創建
StringBuilder
17.Android Service與Activity之間通信的幾種方式
通過Binder對象
通過broadcast(廣播)的形式
18.Android各個版本API的區別
http://blog.csdn.net/lijun952048910/article/details/7980562
19. Android代碼中實現WAP方式聯網(360)
http://blog.csdn.net/asce1885/article/details/7844159
20.如何保證service在后台不被kill
如何保證service在后台不被kill
后台進程保活你需要知道的
微信Android客戶端后台保活經驗分享
關於 Android 進程保活,你所需要知道的一切
一、onStartCommand方法,返回START_STICKY
START_STICKY 在運行onStartCommand后service進程被kill后,那將保留在開始狀態,但是不保留那些傳入的intent。不久后service就會再次嘗試重新創建,因為保留在開始狀態,在創建 service后將保證調用onstartCommand。如果沒有傳遞任何開始命令給service,那將獲取到null的intent。
START_NOT_STICKY 在運行onStartCommand后service進程被kill后,並且沒有新的intent傳遞給它。Service將移出開始狀態,並且直到新的明顯的方法(startService)調用才重新創建。因為如果沒有傳遞任何未決定的intent那么service是不會啟動,也就是期間onstartCommand不會接收到任何null的intent。
START_REDELIVER_INTENT 在運行onStartCommand后service進程被kill后,系統將會再次啟動service,並傳入最后一個intent給onstartCommand。直到調用stopSelf(int)才停止傳遞intent。如果在被kill后還有未處理好的intent,那被kill后服務還是會自動啟動。因此onstartCommand不會接收到任何null的intent。
二、提升service優先級
在AndroidManifest.xml文件中對於intent-filter可以通過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用於廣播。
三、提升service進程優先級
Android中的進程是托管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。Android將進程分為6個等級,它們按優先級順序由高到低依次是: 1.前台進程( FOREGROUND_APP) 2.可視進程(VISIBLE_APP ) 3. 次要服務進程(SECONDARY_SERVER ) 4.后台進程 (HIDDEN_APP) 5.內容供應節點(CONTENT_PROVIDER) 6.空進程(EMPTY_APP) 當service運行在低內存的環境時,將會kill掉一些存在的進程。因此進程的優先級將會很重要,可以使用startForeground 將service放到前台狀態。這樣在低內存時被kill的幾率會低一些。
四、onDestroy方法里重啟service
service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,重新啟動service;
五、Application加上Persistent屬性
六、監聽系統廣播判斷Service狀態
通過系統的一些廣播,比如:手機重啟、界面喚醒、應用狀態改變等等監聽並捕獲到,然后判斷我們的Service是否還存活,別忘記加權限啊。
21.Requestlayout,onlayout,onDraw,DrawChild區別與聯系(獵豹)
22.invalidate()和postInvalidate() 的區別及使用(百度)
23.Android動畫框架實現原理
Animation框架定義了透明度,旋轉,縮放和位移幾種常見的動畫,而且控制的是整個View,實現原理是每次繪制視圖時View所在的ViewGroup中的drawChild函數獲取該View的Animation的Transformation值,然后調用canvas.concat(transformToApply.getMatrix()),通過矩陣運算完成動畫幀,如果動畫沒有完成,繼續調用invalidate()函數,啟動下次繪制來驅動動畫,動畫過程中的幀之間間隙時間是繪制函數所消耗的時間,可能會導致動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,並不能相應事件。
24.Android為每個應用程序分配的內存大小是多少?(美團)
25.Android View刷新機制(百度、美團)
由ViewRoot對象的performTraversals()方法調用draw()方法發起繪制該View樹,值得注意的是每次發起繪圖時,並不會重新繪制每個View樹的視圖,而只會重新繪制那些“需要重繪”的視圖,View類內部變量包含了一個標志位DRAWN,當該視圖需要重繪時,就會為該View添加該標志位。
調用流程 :
mView.draw()開始繪制,draw()方法實現的功能如下:
繪制該View的背景
為顯示漸變框做一些准備操作(見5,大多數情況下,不需要改漸變框)
調用onDraw()方法繪制視圖本身 (每個View都需要重載該方法,ViewGroup不需要實現該方法)
調用dispatchDraw ()方法繪制子視圖(如果該View類型不為ViewGroup,即不包含子視圖,不需要重載該方法)值得說明的是,ViewGroup類已經為我們重寫了dispatchDraw ()的功能實現,應用程序一般不需要重寫該方法,但可以重載父類函數實現具體的功能。
26.LinearLayout對比RelativeLayout(百度)
RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,也會調用子View2次onMeasure 2.RelativeLayout的子View如果高度和RelativeLayout不同,則會引發效率問題,當子View很復雜時,這個問題會更加嚴重。如果可以,盡量使用padding代替margin。 3.在不影響層級深度的情況下,使用LinearLayout和FrameLayout而不是RelativeLayout。 最后再思考一下文章開頭那個矛盾的問題,為什么Google給開發者默認新建了個RelativeLayout,而自己卻在DecorView中用了個LinearLayout。因為DecorView的層級深度是已知而且固定的,上面一個標題欄,下面一個內容欄。采用RelativeLayout並不會降低層級深度,所以此時在根節點上用LinearLayout是效率最高的。而之所以給開發者默認新建了個RelativeLayout是希望開發者能采用盡量少的View層級來表達布局以實現性能最優,因為復雜的View嵌套對性能的影響會更大一些。
27.優化自定義view(百度、樂視、小米)
為了加速你的view,對於頻繁調用的方法,需要盡量減少不必要的代碼。先從onDraw開始,需要特別注意不應該在這里做內存分配的事情,因為它會導致GC,從而導致卡頓。在初始化或者動畫間隙期間做分配內存的動作。不要在動畫正在執行的時候做內存分配的事情。
你還需要盡可能的減少onDraw被調用的次數,大多數時候導致onDraw都是因為調用了invalidate().因此請盡量減少調用invaildate()的次數。如果可能的話,盡量調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。
另外一個非常耗時的操作是請求layout。任何時候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每一個view的大小。如果找到有沖突的值,它會需要重新計算好幾次。另外需要盡量保持View的層級是扁平化的,這樣對提高效率很有幫助。
如果你有一個復雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操作。與內置的view不同,自定義的view可以使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展示了如何繼承ViewGroup作為自定義view的一部分。PieChart 有子views,但是它從來不測量它們。而是根據他自身的layout法則,直接設置它們的大小。
28.ContentProvider(樂視)
29.fragment生命周期
30.volley解析(美團、樂視)
31.Android Glide源碼解析
32.Android 設計模式
http://blog.csdn.net/xhmj12/article/category/6204421
33.架構設計(搜狐)
Android App的設計架構:MVC,MVP,MVVM與架構經驗談
34.Android屬性動畫特性(樂視、小米)
如果你的需求中只需要對View進行移動、縮放、旋轉和淡入淡出操作,那么補間動畫確實已經足夠健全了。但是很顯然,這些功能是不足以覆蓋所有的場景的,一旦我們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操作,那么補間動畫就不能再幫我們忙了,也就是說它在功能和可擴展方面都有相當大的局限性,那么下面我們就來看看補間動畫所不能勝任的場景。
原文鏈接:http://www.jianshu.com/p/4174eec7183b
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。
