2019-2020年Android最新整理面試題

 

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

  onCreate():表示Activity正在被創建,常用來初始化工作,比如調用setContentView加載界面佈局資源,初始化Activity所需數據等;

onStart():表示Activity正在被啓動,此時Activity可見但不在前臺,還處於後臺,無法與用戶交互;

onResume():表示Activity獲得焦點,此時Activity可見且在前臺並開始活動,這是與onStart的區別所在;

onPause():表示Activity正在停止,此時可做一些存儲數據、停止動畫等工作,但是不能太耗時,因爲這會影響到新Activity的顯示,onPause必須先執行完,新Activity的onResume纔會執行;

onStop():表示Activity即將停止,可以做一些稍微重量級的回收工作,比如註銷廣播接收器、關閉網絡連接等,同樣不能太耗時;

onRestart():表示Activity正在重新啓動,一般情況下,當前Acitivty從不可見重新變爲可見時,OnRestart就會被調用;

onDestroy():表示Activity即將被銷燬,這是Activity生命週期中的最後一個回調,常做回收工作、資源釋放

2.說下 Activity的四種啓動模式、應用場景 ? 

standard標準模式:每次啓動一個Activity都會重新創建一個新的實例,不管這個實例是否已經存在,此模式的Activity默認會進入啓動它的Activity所屬的任務棧中;

singleTop棧頂複用模式:如果新Activity已經位於任務棧的棧頂,那麼此Activity不會被重新創建,同時會回調onNewIntent方法,如果新Activity實例已經存在但不在棧頂,那麼Activity依然會被重新創建; 

singleTask棧內複用模式:只要Activity在一個任務棧中存在,那麼多次啓動此Activity都不會重新創建實例,並回調onNewIntent方法,此模式啓動Activity A,系統首先會尋找是否存在A想要的任務棧,如果不存在,就會重新創建一個任務棧,然後把創建好A的實例放到棧中;    

singleInstance單實例模式:這是一種加強的singleTask模式,具有此種模式的Activity只能單獨地位於一個任務棧中,且此任務棧中只有唯一一個實例;

3.隊列和棧的區別

隊列(Queue):是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表;

棧(Stack):是限定只能在表的一端進行插入和刪除操作的線性表。

區別如下:

一、規則不同

       1. 隊列:先進先出(First In First Out)FIFO

       2. 棧:先進後出(First In Last Out )FILO

二、對插入和刪除操作的限定不同

       1. 隊列:只能在表的一端進行插入,並在表的另一端進行刪除;

       2. 棧:只能在表的一端插入和刪除。

三、遍歷數據速度不同

       1. 隊列:基於地址指針進行遍歷,而且可以從頭部或者尾部進行遍歷,但不能同時遍歷,無需開闢空間,因爲在遍歷的過程中不影響數據結構,所以遍歷速度要快;

       2. 棧:只能從頂部取數據,也就是說最先進入棧底的,需要遍歷整個棧才能取出來,而且在遍歷數據的同時需要爲數據開闢臨時空間,保持數據在遍歷前的一致性。

4,設備橫豎屏切換的時候,生面週期的變化

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

設置Activity的android:configChanges=”orientation”時,

  • 在Android5.1 即API 23級別下,切屏還是會重新調用各個生命週期,切橫、豎屏時只會執行一次
  • 在Android9 即API 28級別下,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged方法

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

onConfigurationChanged方法


5.談一談Fragment的生命週期?

Fragment從創建到銷燬整個生命週期中涉及到的方法依次爲:

onAttach()onCreate()onCreateView()onActivityCreated()onStart()onResume()onPause()onStop()onDestroyView()onDestroy()onDetach()

其中和Activity有不少名稱相同作用相似的方法,而不同的方法有:

  • onAttach():當Fragment和Activity建立關聯時調用;
  • onCreateView():當fragment創建視圖調用,在onCreate之後;
  • onActivityCreated():當與Fragment相關聯的Activity完成onCreate()之後調用;
  • onDestroyView():在Fragment中的佈局被移除時調用;
  • onDetach():當Fragment和Activity解除關聯時調用;

6.Service生命週期                                                                                                   

  • onCreate()       首次創建服務時,系統將調用此方法。如果服務已在運行,則不會調用此方法,該方法只調用一次。
  • onStartCommand()         當另一個組件通過調用startService()請求啓動服務時,系統將調用此方法。
  • onDestroy()         當服務不再使用且將被銷燬時,系統將調用此方法。
  • onBind()          當另一個組件通過調用bindService()與服務綁定時,系統將調用此方法。
  • onUnbind()      當另一個組件通過調用unbindService()與服務解綁時,系統將調用此方法。
  • onRebind()      當舊的組件與服務解綁後,另一個新的組件與服務綁定,onUnbind()返回true時,系統將調用此方法。

7.Service的兩種啓動方式?區別在哪?

  • startService():通過這種方式調用startService,onCreate()只會被調用一次,多次調用startSercie會多次執行onStartCommand()和onStart()方法。如果外部沒有調用stopService()或stopSelf()方法,service會一直運行。
  • bindService():如果該服務之前還沒創建,系統回調順序爲onCreate()→onBind()。如果調用bindService()方法前服務已經被綁定,多次調用bindService()方法不會多次創建服務及綁定。如果調用者希望與正在綁定的服務解除綁定,可以調用unbindService()方法,回調順序爲onUnbind()→onDestroy();

8.廣播有幾種形式 ? 都有什麼特點 ?

  •  普通廣播:開發者自身定義 intent的廣播(最常用),所有的廣播接收器幾乎會在同一時刻接受到此廣播信息,接受的先後順序隨機;
  • 有序廣播:發送出去的廣播被廣播接收者按照先後順序接收,同一時刻只會有一個廣播接收器能夠收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞,且優先級(priority)高的廣播接收器會先收到廣播消息。有序廣播可以被接收器截斷使得後面的接收器無法收到它;
  • 本地廣播:僅在自己的應用內發送接收廣播,也就是隻有自己的應用能收到,數據更加安全,效率更高,但只能採用動態註冊的方式;
  • 粘性廣播:這種廣播會一直滯留,當有匹配該廣播的接收器被註冊後,該接收器就會收到此條廣播;

9.BroadcastReceiver註冊方式與區別 

10.Android中IPC方式、各種方式優缺點,爲什麼選擇Binder?

Binder好在哪呢?

傳輸效率高、可操作性強、實現C/S架構方便、安全性高

11.Binder機制的作用?

Linux系統將一個進程分爲用戶空間內核空間。對於進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,爲了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即Android的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式。

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

  • View的工作流程主要是指measure、layout、draw這三大流程,即測量、佈局和繪製,其中measure確定View的測量寬/高,layout確定View的最終寬/高四個頂點的位置,而draw則將View繪製到屏幕
  • View的繪製過程遵循如下幾步:
    • 繪製背景 background.draw(canvas)
    • 繪製自己(onDraw)
    • 繪製 children(dispatchDraw)
    • 繪製裝飾(onDrawScollBars)

13.什麼是ANR ? 什麼情況會出現ANR ?如何避免 ? 在不看代碼的情況下如何快速定位出現ANR問題所在 ?

  • ANR(Application Not Responding,應用無響應):當操作在一段時間內系統無法處理時,會在系統層面會彈出ANR對話框
  • 產生ANR可能是因爲5s內無響應用戶輸入事件、10s內未結束BroadcastReceiver、20s內未結束Service
  • 想要避免ANR就不要在主線程做耗時操作,而是通過開子線程,方法比如繼承Thread或實現Runnable接口、使用AsyncTask、IntentService、HandlerThread等
  • Process:anr發生的時間和進程,和生成traces文件的時間
    CPUusage ... ago :cpu在anr發生前的使用情況
    CPUusage ...later: cpu在anr後的使用情況
    ABI:         手機的cpu架構
    HEAP:     堆的內存信息
    ANR in: 包名,和類名
    Reason:原因
    TOTAL:總的CPU使用率
    prio:線程的優先級
    tid:線程鎖id  主線程的id爲1  主要看這個線程的
    Sleeping:線程的狀態
    sCount:線程被掛起的次數
    dsCount:線程是否被調試
  • 典型的分析情況

    1.如果TOTAL(總的cpu使用頻率)的和接近100,有可能是因爲當前使用的app佔用的cpu太高,導致系統將你的殺死。
    2.如果TOTAL很小,則說明線程被阻塞了,主線程在等待下條消息的進入,任務在等待時anr。
    3.如果ioWait很高,則說明是io操作導致的

推薦文章:如何快速分析定位ANR

14.線程sleep和wait有什麼區別 

   功能差不多,都用來進行線程控制,他們最大本質的區別是:sleep()不釋放同步鎖,wait()釋放同步鎖.   
   還有用法的上的不同是:sleep(milliseconds)可以用時間指定來使他自動醒過來,如果時間不到你只能調用interreput()來強行打斷;wait()可以用notify()直接喚起.

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

  • ①Item佈局,層級越少越好,使用hierarchyview工具查看優化。
  • ②複用convertView
  • ③使用ViewHolder
  • ④item中有圖片時,異步加載
  • ⑤快速滑動時,不加載圖片
  • ⑥item中有圖片時,應對圖片進行適當壓縮
  • ⑦實現數據的分頁加載

16.Android異步消息處理機制(這個也會經常問到)

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

主要有四個部分:
①. Message (消息)
在線程之間傳遞,可在內部攜帶少量信息,用於不同線程之間交換數據
可以使用what、arg1、arg2字段攜帶整型數據
obj字段攜帶Object對象
②. Handler (處理者)
主要用於發送和處理消息,sendMessage()用來發送消息,最終會回到handleMessage()進行處理
③. MessageQueue (消息隊列)
主要存放所有通過Handler發送的消息,它們會一直存在於隊列中等待被處理
每個線程只有一個MessageQueue
④. Looper (循環器)
調用loop()方法後,會不斷從MessageQueue 取出待處理的消息,然後傳遞到handleMessage進行處理.


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

  • 內存溢出 out of memory:是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。內存溢出通俗的講就是內存不夠用。
  • 內存泄露 memory leak:是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光

內存泄露原因以及解決:
一、Handler 引起的內存泄漏。
解決:將Handler聲明爲靜態內部類,就不會持有外部類SecondActivity的引用,其生命週期就和外部類無關,
如果Handler裏面需要context的話,可以通過弱引用方式引用外部類
二、單例模式引起的內存泄漏。
解決:Context是ApplicationContext,由於ApplicationContext的生命週期是和app一致的,不會導致內存泄漏
三、非靜態內部類創建靜態實例引起的內存泄漏。
解決:把內部類修改爲靜態的就可以避免內存泄漏了
四、非靜態匿名內部類引起的內存泄漏。
解決:將匿名內部類設置爲靜態的。
五、註冊/反註冊未成對使用引起的內存泄漏。
註冊廣播接受器、EventBus等,記得解綁。
六、資源對象沒有關閉引起的內存泄漏。
在這些資源不使用的時候,記得調用相應的類似close()、destroy()、recycler()、release()等方法釋放。
七、集合對象沒有及時清理引起的內存泄漏。
通常會把一些對象裝入到集合中,當不使用的時候一定要記得及時清理集合,讓相關對象不再被引用。

 

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