2019年Android崗位BAT等大廠面試題,希望對新的一年的你有所幫助


2019年Android崗位BAT等大廠面試題知識點小結

2019年了搜集了很多面試題,希望能對大家有所幫助

1.View的繪制流程;自定義View如何考慮機型適配;自定義View的事件分發機制;View和ViewGroup分別有哪些事件分發相關的回調方法;自定義View如何提供獲取View屬性的接口。

 

View的繪制流程:

流程一:mesarue()過程;

流程二:layout布局過程;

流程三:draw()繪圖過程。

詳情:http://blog.csdn.net/qinjuning/article/details/7110211/

 

自定義View如何考慮機型適配:

這篇博文解決了Android適配的絕大多數問題:

http://blog.csdn.net/zhaokaiqiang1992/article/details/45419023

 

自定義View的事件分發機制:

對於 dispatchTouchEvent,onTouchEvent,return true是終結事件傳遞。return false 是回溯到父View的onTouchEvent方法。

ViewGroup 想把自己分發給自己的onTouchEvent,需要攔截器onInterceptTouchEvent方法return true 把事件攔截下來。

ViewGroup 的攔截器onInterceptTouchEvent 默認是不攔截的,所以return super.onInterceptTouchEvent()=return false;

View 沒有攔截器,為了讓View可以把事件分發給自己的onTouchEvent,View的dispatchTouchEvent默認實現(super)就是把事件分發給自己的onTouchEvent。

對於ACTION_MOVE、ACTION_UP總結:ACTION_DOWN事件在哪個控件消費了(return true), 那么ACTION_MOVE和ACTION_UP就會從上往下(通過dispatchTouchEvent)做事件分發往下傳,就只會傳到這個控件,不會繼續往下傳,如果ACTION_DOWN事件是在dispatchTouchEvent消費,那么事件到此為止停止傳遞,如果ACTION_DOWN事件是在onTouchEvent消費的,那么會把ACTION_MOVE或ACTION_UP事件傳給該控件的onTouchEvent處理並結束傳遞。

 

詳情:http://www.jianshu.com/p/e99b5e8bd67b

以及下面這個的第五部分:

http://imtianx.cn/2016/12/17/Android%20View%20%E7%9A%84%E4%BA%8B%E4%BB%B6%E4%BD%93%E7%B3%BB/

 

View和ViewGroup分別有哪些事件分發相關的回調方法:

View中跟事件分發機制有關的就是兩個方法:dispatchTouchEvent和onTouchEvent。整個View的事件轉發流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent

在dispatchTouchEvent中會進行OnTouchListener的判斷,如果OnTouchListener不為null且返回true,則表示事件被消費,onTouchEvent不會被執行;否則執行onTouchEvent。

 

對於ViewGroup中的分發事件:

如果ViewGroup找到了能夠處理該事件的View,則直接交給子View處理,自己的onTouchEvent不會被觸發;

可以通過復寫onInterceptTouchEvent(ev)方法,攔截子View的事件(即return true),把事件交給自己處理,則會執行自己對應的onTouchEvent方法

子View可以通過調用getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup對其MOVE或者UP事件進行攔截;

詳情:http://blog.csdn.net/lmj623565791/article/details/38960443

http://blog.csdn.net/lmj623565791/article/details/39102591

 

自定義View如何提供獲取View屬性的接口:

關於View所要具備的一般功能,View類中都有了基本的實現,比如確定位置,它有layout方法,當然,這個只適用於ViewGroup,實現自己的ViewGroup時,才需要修改該方法。確定大小,它有onMeasure方法,如果你不滿意默認的確認大小的方法,也可以自己定義。改變默認的繪制,就覆寫onDraw方法。

詳情:http://www.jianshu.com/p/d507e3514b65

 

2.Art和Dalvik對比;虛擬機原理,如何自己設計一個虛擬機(內存管理,類加載,雙親委派);JVM內存模型及類加載機制;內存對象的循環引用及避免

 

Art和Dalvik對比:

Dalvik是Google公司自己設計用於Android平台的虛擬機。

ART即Android Runtime

Dalvik和ART的幾點區別:

dalvik是執行的時候編譯+運行,安裝比較快,開啟應用比較慢,應用占用空間小

ART是安裝的時候就編譯好了,執行的時候直接就可以運行的,安裝慢,開啟應用快,占用空間大

用個比喻來說就是,騎自行車

dalvik 是已經折疊起來的自行車,每次騎都要先組裝自行車才能騎

ART 是已經組裝好的自行車,每次騎直接上車就能走人

詳情:http://www.jb51.net/article/88708.htm

 

虛擬機原理,如何自己設計一個虛擬機(內存管理,類加載,雙親委派):

在加載階段,java虛擬機需要完成以下3件事:

a.通過一個類的全限定名來獲取定義此類的二進制字節流。

b.將定義類的二進制字節流所代表的靜態存儲結構轉換為方法區的運行時數據結構。

c.在java堆中生成一個代表該類的java.lang.Class對象,作為方法區數據的訪問入口。

 

類加載:

從類被加載到虛擬機內存中開始,到卸載出內存為止,類的生命周期包括加載(Loading)、驗證(Verification)、准備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)7個階段

 

雙親委派:

系統提供的類加載器主要有下面3個:

.啟動類加載器(Bootstarp ClassLoader)

.擴展類加載器(Extension ClassLoader)

.應用程序類加載器(Application ClassLoader)

注意:上述三個JDK提供的類加載器雖然是父子類加載器關系,但是沒有使用繼承,而是使用了組合關系。

詳情:http://blog.csdn.net/ochangwen/article/details/51473120

http://blog.csdn.net/ochangwen/article/details/51472311

 

JVM內存模型及類加載機制:

JVM要想執行class文件,首先會將文件載入虛擬機的方法區內,根據類文件的格式相應的存放數據。在需要產生對象時,從方法區中獲取對應的類信息,在堆中建立對象。

詳情:http://blog.csdn.net/dragon_cat_han/article/details/52150955

 

內存對象的循環引用及避免:

如果有兩個或者以上的對象,它們彼此引用,就會造成循環引用。

避免:引用計數GC處理,引用遍歷GC處理。

詳情:http://www.wtoutiao.com/p/11elsk6.html

 

3.內存回收機制與GC算法(各種算法的優缺點以及應用場景);GC原理時機以及GC對象;內存泄露場景及解決方法;OOM的避免及解決方法 

 

內存回收機制與GC算法(各種算法的優缺點以及應用場景):

GC是通過對象是否存活來決定是否進行回收,最常用的判定算法是引用計數算法以及Java中使用的判定算法為根搜索算法(GC Roots Tracing)

常用的垃圾收集算法

a、標記——清除算法(Mark——Sweep)

首先標記出所有需要回收的對象,在標記完成后統一回收掉所有被標記的對象。

缺點:效率問題,標記和清除過程的效率不高;

b、復制算法(Copying)

為了解決標記清除算法的效率問題,復制算法將可用的內存按容量划分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活的對象復制到另一塊上,然后再把已使用過的內存空間一次清理掉。

優點:實現簡單,運行高效

缺點:對內存空間的利用不高,可用內存變成一半,這代價過高

c、標記——整理算法(Mark——Compact)

與標記清除算法的標記階段相同,但標記后會將所有存活的對象向一端移動,然后直接清理掉端邊界以外的內存。這種算法一般用於老年代的內存回收上,因為老年代中對象的存活時間都比較長,可能存在100%存活的極端情況,因此不能選擇Copying算法來進行回收。

d、分代收集算法(Generational Collection)

這種算法只是根據對象的存活周期的不同將內存划分為幾塊,一般都划分為新生代和老年代,這樣可以根據各個年代的特點采用最適當的收集算法。新生代中,每次垃圾收集時都發現有大批對象死去,只有少量存活,因此選取復制算法,只需要付出少量存活對象的復制成本就可以完成收集;老年代中因為對象存活率高,沒有額外的空間對它進行分配擔保,就必須使用“標記——清除”或是“標記——整理”算法來進行回收。在之前的三種算法中已經有所描述。

 

詳情:http://www.open-open.com/lib/view/open1380593930103.html

 

GC原理時機以及GC對象:

JVM 分別對新生代和舊生代采用不同的垃圾回收機制

Java中那些不可達的對象就會變成垃圾。那么什么叫做不可達?其實就是沒有辦法再引用到該對象了。主要有以下情況使對象變為垃圾:

1.對非線程的對象來說,所有的活動線程都不能訪問該對象,那么該對象就會變為垃圾。

2.對線程對象來說,滿足上面的條件,且線程未啟動或者已停止。

GC將負責回收所有“不可達”對象的內存空間。

 

詳情:https://segmentfault.com/a/1190000002579346

 

內存泄露場景及解決方法:

因為靜態變量造成的內存泄漏;

Handler 的錯誤使用;

非靜態內部類的靜態實例的錯誤使用;

不正確使用線程,造成內存泄漏;

資源沒有及時關閉;

 

詳情例子解決方案參見:http://blog.csdn.net/adrian24/article/details/53248255

或者http://www.jianshu.com/p/51072faadf51

 

OOM的避免及解決方法:

高效加載大圖片:

在展示高分辨率圖片的時候,最好先將圖片進行壓縮。壓縮后的圖片大小應該和用來展示它的控件大小相近,在一個很小的ImageView上顯示一張超大的圖片不會帶來任何視覺上的好處,但卻會占用我們相當多寶貴的內存,而且在性能上還可能會帶來負面影響。下面我們就來看一看,如何對一張大圖片進行適當的壓縮,讓它能夠以最佳大小顯示的同時,還能防止OOM的出現。

使用圖片緩存技術:

內存緩存技術對那些大量占用應用程序寶貴內存的圖片提供了快速訪問的方法。其中最核心的類是LruCache (此類在android-support-v4的包中提供) 。這個類非常適合用來緩存圖片,它的主要算法原理是把最近使用的對象用強引用存儲在 LinkedHashMap 中,並且把最近最少使用的對象在緩存值達到預設定值之前從內存中移除。

 

詳情:http://blog.csdn.net/guolin_blog/article/details/9316683

 

4.四大組件及生命周期;ContentProvider的權限管理(讀寫分離,權限控制-精確到表級,URL控制);Activity的四種啟動模式對比;Activity狀態保存於恢復

都是一些基礎知識,詳情歸類下:

Activity:詳細知識:http://blog.csdn.net/amazing7/article/details/51244219

Service:詳細知識:http://blog.csdn.net/amazing7/article/details/51305911

ContentProvider:詳細知識:http://blog.csdn.net/amazing7/article/details/51324022

BroadcastReceiver:詳細知識:http://blog.csdn.net/amazing7/article/details/51352139

ContentProvider的權限管理:http://blog.csdn.net/robertcpp/article/details/51337891

Activity的四種啟動模式對比:http://blog.csdn.net/knlnzhao/article/details/8005277

Activity狀態保存於恢復:http://blog.csdn.net/js331455217/article/details/40930157

 

5.Fragment生命周期;Fragment狀態保存

生命周期及相關:http://blog.csdn.net/amazing7/article/details/51282082

狀態保存:http://www.jianshu.com/p/75dc2f51cd63

 

6.startActivityForResult是哪個類的方法,在什么情況下使用,如果在Adapter中使用應該如何解耦

startActivityForResult是Activity類里的方法,在原Activity里通過Intent跳轉到其他類再跳回到原Activity里時候,回傳數據所用

詳情:http://blog.csdn.net/sunchaoenter/article/details/6612039

 

在Adapter以及其他非Activity類使用的時候,可以將由原Activity類傳入的Context強轉為Activity類,再在原Activity里重寫onActivityResult方法接受到返回值。

 

7.AsyncTask原理及不足;IntentService原理

AsyncTask是一個輕量級的異步類,繼承時候有三個泛型參數:

1. Params,在執行AsyncTask時需要傳入的參數,可用於在后台任務中使用;

2. Progress,后台任務執行時,如果需要在界面上顯示當前的進度,則使用這里指定的泛型作為進度單位;

3. Result,當任務執行完畢后,如果需要對結果進行返回,則使用這里指定的泛型作為返回值類型。

需要重寫四個方法(至少是2個,2和4):

1. onPreExecute(),這個方法會在后台任務開始執行之間調用,用於進行一些界面上的初始化操作,比如顯示一個進度條對話框等。

2. doInBackground(Params...),這個方法中的所有代碼都會在子線程中運行,我們應該在這里去處理所有的耗時任務。任務一旦完成就可以通過return語句來將任務的執行結果進行返回,如果AsyncTask的第三個泛型參數指定的是Void,就可以不返回任務執行結果。注意,在這個方法中是不可以進行UI操作的,如果需要更新UI元素,比如說反饋當前任務的執行進度,可以調用publishProgress(Progress...)方法來完成。

3. onProgressUpdate(Progress...),當在后台任務中調用了publishProgress(Progress...)方法后,這個方法就很快會被調用,方法中攜帶的參數就是在后台任務中傳遞過來的。在這個方法中可以對UI進行操作,利用參數中的數值就可以對界面元素進行相應的更新。

4. onPostExecute(Result),當后台任務執行完畢並通過return語句進行返回時,這個方法就很快會被調用。返回的數據會作為參數傳遞到此方法中,可以利用返回的數據來進行一些UI操作,比如說提醒任務執行的結果,以及關閉掉進度條對話框等。

AnsycTask執行任務時,內部會創建一個進程作用域的線程池來管理要運行的任務,也就就是說當你調用了AsyncTask.execute()后,AsyncTask會把任務交給線程池,由線程池來管理創建Thread和運行Therad,本質上是對Thread+Handler的良好封裝,減少了開發者處理問題的復雜度,提高了開發效率。

AsyncTask缺陷:

最大的缺點:在使用多個異步操作和並需要進行Ui變更時,就變得復雜起來。

其他的參考下面的文章。

詳情:http://blog.csdn.net/liuhe688/article/details/6532519

http://blog.csdn.net/boyupeng/article/details/49001215

IntentService原理

IntentService是繼承於Service並處理異步請求的一個類,在IntentService內有一個工作線程來處理耗時操作,啟動IntentService的方式和啟動傳統Service一樣,同時,當任務執行完后,IntentService會自動停止,而不需要我們去手動控制。

詳情:http://blog.csdn.net/qq_18402085/article/details/50753005

http://blog.csdn.net/ryantang03/article/details/8146154/

 

8.AstncTask+HttpClient與AsyncHttpClient有什么區別

AsyncHttpClient來自android-async-http庫是在Apache的HttpClient庫的基礎上開發構建而成的,這里的異步,是指它所有的網絡請求都是在app的UI線程之外的獨立工作線程中執行。而開發者通過利用Android的消息處理機制,把我們所需要編寫的回調函數放在這個回調函數的創建線程中執行(一般就是UI線程),所以使用起來非常方便除了能應用在開發普通App上,還可以用來開發Service或后台線程,async-http-client庫可以自已分辨是被用在哪一種應用下,不需要額外的設置。

詳情:https://my.oschina.net/u/725054/blog/494494

http://blog.csdn.net/wangpeng047/article/details/19624529

 

9.如何保證一個后台服務不被殺死;比較省電的方式是什么

服務不被殺死分3種來討論

1.系統根據資源分配情況殺死服務

2.用戶通過 settings -> Apps -> Running -> Stop 方式殺死服務

3.用戶通過 settings -> Apps -> Downloaded -> Force Stop 方式殺死服務

第一種情況:

用戶不干預,完全靠系統來控制,辦法有很多。比如 onStartCommand() 方法的返回值設為 START_STICKY ,服務就會在資源緊張的時候被殺掉,然后在資源足夠的時候再恢復。當然也可設置為前台服務,使其有高的優先級,在資源緊張的時候也不會被殺掉。

第二種情況:

用戶干預,主動殺掉運行中的服務。這個過程殺死服務會通過服務的生命周期,也就是會調用 onDestory() 方法,這時候一個方案就是在 onDestory() 中發送廣播開啟自己。這樣殺死服務后會立即啟動。

當然,從理論上來講這個方案是可行的,實驗一下也可以。但有些情況下,發送的廣播在消息隊列中排的靠后,就有可能服務還沒接收到廣播就銷毀了(這是我對實驗結果的猜想,具體執行步驟暫時還不了解)。所以為了能讓這個機制完美運行,可以開啟兩個服務,相互監聽,相互啟動。服務A監聽B的廣播來啟動B,服務B監聽A的廣播來啟動A。經過實驗,這個方案可行,並且用360殺掉后幾秒后服務也還是能自啟的。到這里再說一句,如果不是某些功能需要的服務,不建議這么做,會降低用戶體驗。

第三種情況:

強制關閉就沒有辦法。這個好像是從包的level去關的,並不走完整的生命周期。所以在服務里加代碼是無法被調用的。處理這個情況的唯一方法是屏蔽掉 force stop和 uninstall 按鈕,讓其不可用。方法自己去找吧。當然有些手機自帶的清理功能就是從這個地方清理的,比如華為的清理。所以第三種情況我也沒有什么更好的辦法了。

詳情:http://www.tuicool.com/articles/iu22QnF

 

10.如何通過廣播攔截和abort一條短信;廣播是否可以請求網絡;廣播引起anr的時間限制

目前找到方法都是適用於Android4.4默認短信應用以前的方法:

第一步:新建一個類繼承BroadcastReceiver,並重寫onReceive()方法.

第二步:訂閱短信的廣播Intent,訂閱方法有兩種:

1:使用代碼進行訂閱

2:在AndroidManifest.xml文件中的<application>節點中進行訂閱

 

在Android中,每次廣播消息到來時都會創建BroadcastReceiver實例並執行onReceive() 方法,

onReceive() 方法執行完后,BroadcastReceiver 的實例就會被銷毀。攔截短信的方法就寫在onReceive() 方法里即可。

 

詳情:http://blog.csdn.net/jason0539/article/details/11720419

 

廣播可以監聽網絡狀態,網絡變化等,好像不能請求網絡。

 

在 Android中,程序的響應(Responsive)被活動管理器(Activity Manager)和窗口管理器(Window Manager)這兩個系統服務所監視,當BroadcastReceiver在10秒內沒有執行完畢,Android會認為該程序無響應,所以在 BroadcastReceiver里不能做一些比較耗時的操作,否則會彈出ANR(Application No Response)的對話框。如果需要完成一項比較耗時的工作,應該通過發送Intent給Service,由Service來完成,而不是使用子線程的方法來解決,因為BroadcastReceiver的生命周期很短(在onReceive()執行后BroadcastReceiver的實例就會被銷毀),子線程可能還沒有結束BroadcastReceiver就先結束了。如果BroadcastReceiver結束了,它的宿主進程還在運行,那么 子線程還會繼續執行。但宿主進程此時很容易在系統需要內在時被優先殺死。因為它屬於空進程(沒有任何活動組件的進程)。

詳情:http://blog.csdn.net/wufen1103/article/details/7839107

 

11.進程間通信,AIDL

aidl是 Android Interface definition language的縮寫,一看就明白,它是一種android內部進程通信接口的描述語言,通過它我們可以定義進程間的通信接口

詳情:http://blog.csdn.net/stonecao/article/details/6425019

 

12.Handler機制及底層實現

詳情:http://www.jianshu.com/p/9e4d1fab0f36

http://blog.csdn.net/itachi85/article/details/8035333

 

13.Binder機制及底層實現

詳情:http://blog.csdn.net/weijinqian0/article/details/52233529

 

14.ApplicationContext和ActivityContext的區別

Context,中文直譯為“上下文”,它是一個抽象類,描述的是一個應用程序環境的信息,通過它我們可以獲取應用程序的資源和類,也包括一些應用級別操作。

應用程序創建Context實例的情況一共有三種:

1、創建Application 對象時

2、創建Service對象時

3、創建Activity對象時

其中對於ApplicationContext,每個應用程序在第一次啟動時,都會首先創建Application對象。如果對應用程序啟動一個Activity(startActivity)流程比較清楚的話,創建Application的時機在創建handleBindApplication()方法中,該函數位於 ActivityThread.java類中;

對於ActivityContext,通過startActivity()或startActivityForResult()請求啟動一個Activity時,如果系統檢測需要新建一個Activity對象時,就會回調handleLaunchActivity()方法,該方法繼而調用performLaunchActivity()方法,去創建一個Activity實例,並且回調onCreate(),onStart()方法等, 函數都位於 ActivityThread.java類。

 

 

 

詳情:http://blog.csdn.net/qinjuning/article/details/7310620

 

 https://www.jianshu.com/p/0f89f93c8faf


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM