本文是Android面試題整理中的一篇,結合右下角目錄食用更佳,包括:html
分爲四個層次:linux內核;libraies和Android runntime;framework;Application java
- Activity:Activity是Android程序與用戶交互的窗口,對用戶來講是可見的
- service:後臺服務於Activity,是一個服務,不可見
- Content Provider:對外提提供數據
- BroadCast Receiver:接受一種或者多種Intent做觸發事件,接受相關消息,作一些簡單處理
- 前臺進程
- 可見進程
- 服務進程
- 後臺進程
- 空進程
- res目錄下的資源文件會在R文件中生成對應的id,asset不會\
- res目錄下的文件在生成apk時,除raw(即res/raw)目錄下文件不進行編譯外,都會被編譯成二進制文件;asset目錄下的文件不會進行編譯
- asset目錄容許有子目錄
- 沙箱化能夠提高安全性和效率
- Android的底層內核爲Linux,所以繼承了Linux良好的安全性,並對其進行了優化。在Linux中,一個用戶對應一個uid,而在Android中,(一般)一個APP對應一個uid,擁有獨立的資源和空間,與其餘APP互不干擾。若有兩個APP A和B,A並不能訪問B的資源,A的崩潰也不會對B形成影響,從而保證了安全性和效率
- 沒有任何設置時,會調用整個生命週期方法,而且會調用onSaveInstance和onRestoreInstanceState方法
- 在Manifest中爲Activity設置android:configChanges="orientation"時,只調用onConfigChanges方法
- android:configChanges="orientation"屬性有可能不起做用,依然會調用整個生命週期方法,這是由於不一樣版本處理方式可能不一樣,有時候還須要加上android:configChanges="orientation|keyboardHidden|screenSize"等。
- 非用戶主動明確結束(按back鍵,自定義click方法調用finish)時都會調用onSaveInstanceState:
- 屏幕旋轉
- 按HOME鍵
- 內存不足
- 從一個activity啓動另外一個activity
- 這個方法的調用時機是在onStop前,可是它和onPause沒有既定的時序關係
- View有惟一的ID
- View的初始化時要調用setSaveEnabled(true)
對Activity配置了android:configChanges="xxx"屬性以後,Activity就不會在對應變化發生時從新建立,而是調用Activity的onConfigurationChanged方法。經常使用的有local:設備的本地位置發生了變化,通常指切換了系統語言;keyboardHidden:鍵盤的可訪問性發生了變化,好比用戶調出了鍵盤;orientation:屏幕方向發生了變化,好比旋轉了手機屏幕。linux
- A啓動B:A.onPause()→B.onCreate()→B.onStart()→B.onResume()→A.onStop
- B返回A:B.onPause()→A.onRestart()/A.onCreate()→A.onStart()→A.onResume()→B.onStop()
- 在onCreate中執行:onCreate -> onDestroy
- 在onStart中執行:onCreate -> onStart -> onStop -> onDestroy
- 在onResume中執行:onCreate -> onStart -> onResume -> onpause -> onStop -> onDestroy
- 能夠用Google的LifeCycle框架 0. 引入LifeCycle框架
- 將控件實現LifecycleObserver接口
- 在Activity中中註冊控件:getLifeCycle().addObderver(View);
- 在控件中使用: @OnLifecycleEvent(Lifecycle.Event.ON_START)
- standard:每一次啓動,都會生成一個新的實例,放入棧頂中
- singleTop:經過singelTop啓動Activity時,若是發現有須要啓動的實例正在棧頂,責直接重用,不然生成新的實例
- singleTask:經過singleTask啓動Activity時,若是發現有須要啓動的實例正在棧中,責直接移除它上邊的實例,並重用該實例,不然生成新的實例
- singleInstance:經過singleTask啓動Activity時,會啓用一個新的棧結構,並將新生成的實例放入棧中。
- 任務相關性,標識一個Activity所需的任務棧的名字。默認狀況下,全部的Activity所需的任務棧的名字是應用的包名,固然也能夠單獨指定TaskAffinity屬性。
- TaskAffinity屬性主要和singleTask啓動模式和allowTaskRepeating屬性配對使用,在其餘狀況下使用沒有意義
- 當TaskAffinity和singleTask啓動模式配對使用的時候,它是具備該模式的Activity的目前任務棧的名字,待啓動的Activity會運行在名字和TaskAffinity相同的任務棧中
- 當TaskAffinity和allowTaskReparenting結合的時候,當一個應用A啓動了應用B的某個Activity C後,若是Activity C的allowTaskReparenting屬性設置爲true的話,那麼當應用B被啓動後,系統會發現Activity C所需的任務棧存在了,就將Activity C從A的任務棧中轉移到B的任務棧中。
- TaskAffinity配合singleTask使用,指定任務棧:若是沒有TaskAffinity指定的任務棧,則開啓新棧
- allowTaskReparenting配合standard和singleTop使用,標明該Activity的任務棧能夠從新設置
設置了singleTask啓動模式的Activity,它在啓動的時會先在系統中查看屬性值affinity等於它的屬性值taskAffinity ( taskAffinity默認爲包名 ) 的任務棧是否存在。若是存在這樣的任務棧,它就會在這個任務棧中啓動,不然就會在新任務棧中啓動。android
當Intent對象包含FLAG_ACTIVITY_NEW_TASK標記時,系統在查找時仍然按Activity的taskAffinity屬性進行匹配,若是找到一個任務棧的taskAffinity與之相同,就將目標Activity壓入此任務棧中,若是找不到則建立一個新的任務棧。git
設置了singleTask啓動模式的Activity在已有的任務棧中已經存在相應的Activity實例,再啓動它時會把這個Activity實例上面的Activity所有結束掉。也就是說singleTask自帶clear top的效果。github
IntentFilter中的過濾信息有action、category、data,爲了匹配過濾列表,須要同時匹配過濾列表中的action、category、data信息,不然匹配失敗。面試
- PackageManager的resolveActivity方法或者Intent的resolveActivity方法:若是找不到就會返回null
- PackageManager的queryIntentActivities方法:它返回全部成功匹配的Activity信息
經過在Application中註冊Activity生命週期的監聽函數Application.registerActivityLifecycleCallbacks()shell
一個Activity已經啓動,當再次啓動它時,若是他的啓動模式(如SingleTask,SingleTop)標明不須要從新啓動,會調用onNewIntent數據庫
使用adb shell am 命令 :如adb shell am start com.example.fuchenxuan/.MainActivity 或者 adb shell am broadcast -a magcomm.action.TOUCH_LETTER緩存
- activity.runOnUiThread(runnable)
- 經過主線程中的Handler進行更新
- 經過View的post()或者postDelayed方法進行更新
- Intent
- BroadCast或者LocalBroadCast
- 數據存儲的方式
- 靜態變量
- start
- bind
- 如上Activity和Activity的通訊方式
- bind方式啓動時能夠經過ServiceConnection通訊:在SerVice的onBind方法中返回一個binder,該binder能夠是AIDL方法產生的,也能夠是Messenger方法產生的
- 這是沒用任何關係的兩個概念,servie是系統的組件,Thread是CPU運行的最小單元
- Service不可見,咱們能夠把Service當成是不可見的Activity,用於在後臺執行一些服務;
- Service能夠運行在任意線程上,若是咱們生成它時沒有作特殊說明,那麼它運行在主線程上
- 不少時候咱們須要在Activity中開啓一個Service,再在Service中開啓一個線程,這麼作的緣由是Service只會初始化一次,咱們能夠隨時找到Service中生成的thread,使用場景舉例:
- 如咱們須要在多個Activity中對同一個thread進行控制時;
- 若是你的 Thread 須要不停地隔一段時間就要鏈接服務器作某種同步的話,該 Thread 須要在 Activity 沒有start的時候也在運行。這個時候當你 start 一個 Activity 就沒有辦法在該 Activity 裏面控制以前建立的 Thread。所以你便須要建立並啓動一個 Service ,在 Service 裏面建立、運行並控制該 Thread,這樣便解決了該問題
這是由於Activity很難對Thread進行控制,當Activity被銷燬以後,就沒有任何其它的辦法能夠再從新獲取到以前建立的子線程的實例。並且在一個Activity中建立的子線程,另外一個Activity沒法對其進行操做。可是Service就不一樣了,全部的Activity均可以與Service進行關聯,而後能夠很方便地操做其中的方法,即便Activity被銷燬了,以後只要從新與Service創建關聯,就又可以獲取到原有的Service中Binder的實例。所以,使用Service來處理後臺任務,Activity就能夠放心地finish,徹底不須要擔憂沒法對後臺任務進行控制的狀況。
- IntentService 是繼承自 Service,內部經過HandlerThread啓動一個新線程處理耗時操做麼,能夠看作是Service和HandlerThread的結合體,在完成了使命以後會自動中止,適合須要在工做線程處理UI無關任務的場景
- 若是啓動 IntentService 屢次,那麼每個耗時操做會以工做隊列的方式在 IntentService 的 onHandleIntent 回調方法中執行,依次去執行,使用串行的方式,執行完自動結束。
- 在全部任務執行完畢後,自動結束生命
- 在manifest中靜態註冊:廣播是常駐的,App關閉後仍能接收廣播,喚醒App
- 動態的註冊和註銷:動態註冊的廣播生命週期和他的宿主相同,或者調用註銷方法註銷廣播
- 無序廣播:經過mContext.sendBroadcast(Intent)或mContext.sendBroadcast(Intent, String)發送的是無序廣播(後者加了權限);
- 經過mContext.sendOrderedBroadcast(Intent, String, BroadCastReceiver, Handler, int, String, Bundle)發送的是有序廣播(再也不推薦使用)。
- 在無序廣播中,全部的Receiver會接收到相同廣播;而在有序廣播中,咱們能夠爲Receiver設置優先級,優先級高的先接收廣播,並有權對廣播進行處理和決定要不要繼續向下傳送
- BroadcastReceiver的生命週期只有一個回調方法onReceive(Context context, Intent intent);沒法進行耗時操做,即便啓動線程處理,也是出於非活動狀態,有可能被系統殺掉。
- 若是須要進行耗時操做,能夠啓動一個service處理。
- 繼承BroadcastReceiver,重寫onReceive()方法。
- 經過Binder機制向ActivityManagerService註冊廣播。
- 經過Binder機制向ActivityMangerService發送廣播。
- ActivityManagerService查找符合相應條件的廣播(IntentFilter/Permission)的BroadcastReceiver,將廣播發送到BroadcastReceiver所在的消息隊列中。
- BroadcastReceiver所在消息隊列拿到此廣播後,回調它的onReceive()方法。
- 廣播是經過Intent攜帶須要傳遞的數據的
- Intent是經過Binder機制實現的
- Binder對數據大小有限制,不一樣room不同,通常爲1M
本地廣播,只有本進程中的receivers能接收到此廣播
實現原理(監聽者模式):
- LocalBroadcastManager是一個單例
- 在LocalBroadcastManager實例中維護一個Action和ReceiverRecord的Map.(ReceiverRecord是reveiver和intentfilter的組合)
- 當調用LocalBroadcastManager的sendBroadcast方法時,會從2中的map找到合適的receiver,讓後加到待執行的隊列mPendingBroadcasts,並經過Handler發送一個空消息(此Handler運行在主線程中,是建立manager時建立的)
- handler 的handle方法收到消息,從mPendingBroadcasts取出receiver並調用onreceive方法
其餘:刪除方法是經過一個輔助的hashmap實現的,hashmap存儲了receiver和receiverRecord
- 準確的說,ContentProvider是一個APP間共享數據的接口。一個程序能夠經過實現一個Content provider的抽象接口將本身的數據徹底暴露出去,數據能夠是SqLite中的,也能夠是文件或者其餘類型。
- 使用方式:
- 在A APP中實現建ContentProvider,並在Manifest中生命它的Uri和權限
- 在B APP中註冊權限,並經過ContentResolver和Uri進行增刪改查
- 擴展:ContentProvider底層是經過Binder機制來實現跨進程間通訊,經過匿名共享內存方式進行數據的傳輸 一個應用進程有16個Binder線程去和遠程服務進行交互,而每一個線程可佔用的緩存空間是128KB,超過會報異常。
- ContentProvider和調用者在同一個進程,ContentProvider的方法(query/insert/update/delete等)和調用者在同一線程中
- ContentProvider和調用者在不一樣的進程,ContentProvider的方法會運行在它自身所在進程的一個Binder線程中
- ContentProvider:管理數據,提供數據的增刪改查操做,數據源能夠是數據庫、文件、XML、網絡等,ContentProvider爲這些數據的訪問提供了統一的接口,能夠用來作進程間數據共享。
- ContentResolver:ContentResolver能夠不一樣URI操做不一樣的ContentProvider中的數據,外部進程能夠經過ContentResolver與ContentProvider進行交互。
- ContentObserver:觀察ContentProvider中的數據變化,並將變化通知給外界。
onAttach -> onCreate -> onCreateView -> onActivityCreate -> onStart -> onResume -> onPause -> onStop -> onDestoryView -> onDestory -> onDetach
舉例:getActivity()空指針:這種狀況通常發生在在異步任務裏調用getActivity(),而Fragment已經onDetach()。
- Fragment爲了解決Andriod碎片化而產生的
- Fragment和View都有助於界面複用
- Fragment的複用粒度更大,包含生命週期和業務邏輯,一般包含好幾個View
- View一般更關注視圖的實現
https://www.nowcoder.com/discuss/3043
http://weixin.niurenqushi.com/article/2017-03-17/4790406.html
https://blog.csdn.net/vfush/article/details/51481127
https://blog.csdn.net/vfush/article/details/51790079