主頁 > 移動端開發 > 【干貨】2021最新《Android高級開發面試題2.0》中高級程式員必備“面試寶典”

【干貨】2021最新《Android高級開發面試題2.0》中高級程式員必備“面試寶典”

2021-08-08 08:00:58 移動端開發

目錄

  • 1.Activity
  • 2.Service
  • 3.BroadcastReceiver
  • 4.ContentProvider
  • 5.Handler
  • 6.View繪制
  • 7.View事件分發
  • 8.RecycleView
  • 9.Viewpager&Fragment
  • 10.Webview
  • 11.影片
  • 12.Bitmap
  • 13.mvc&mvp&mvvm
  • 14.Binder
  • 15.記憶體泄漏&記憶體溢位
  • 16.性能優化
  • 17.Window&WindowManager
  • 18.AMS
  • 19.系統啟動
  • 20.App啟動&打包&安裝
  • 21.序列化
  • 22.Art & Dalvik及其區別
  • 23.模塊化&組件化
  • 24.熱修復&插件化
  • 25.AOP
  • 26.jectpack
  • 27.開源框架

1.Activity

1.1.Activity的啟動流程

Activity跨行程啟動

啟動流程:

點擊桌面App圖示,Launcher行程采用Binder IPC向system_server行程發起startActivity請求;

system_server行程接收到請求后,向zygote行程發送創建行程的請求;

Zygote行程fork出新的子行程,即App行程;

App行程,通過Binder IPC向sytem_server行程發起attachApplication請求;

system_server行程在收到請求后,進行一系列準備作業后,再通過binder IPC向App進 程發送scheduleLaunchActivity請求;

App行程的binder執行緒(ApplicationThread)在收到請求后,通過handler向主執行緒發送LAUNCH_ACTIVITY訊息;

主執行緒在收到Message后,通過發射機制創建目標Activity,并回呼Activity.onCreate()等方法,

Activity行程內啟動

請求行程A:startActivity—(hook插入點1) (AMP,ActivityManager代理物件)——> system_server行程:AMS(ActivityManagerService)

決議Activity資訊、處理啟動引數、scheduleLaunchActivity/mH中EXECUTE_TRANSACTION訊息處理(Android P)–>

回到請求行程A:ApplicationThread --> ActivityThread -(hook插入點2)-> Activity生命周期

()

1.2.onSaveInstanceState(),onRestoreInstanceState的掉用時機

1.2.1onSaveInstanceState(Bundle outState)會在以下情況被呼叫:

1.2.1.1、從最近應用中選擇運行其他的程式時,

1.2.1.2、當用戶按下HOME鍵時,

1.2.1.3、螢屏方向切換時(無論豎屏切橫屏還是橫屏切豎屏都會呼叫),

1.2.1.4、按下電源按鍵(關閉螢屏顯示)時,

1.2.1.5、從當前activity啟動一個新的activity時,

onPause -> onSaveInstanceState -> onStop,

1.2.2onRestoreInstanceState(Bundle outState)會在以下情況被呼叫:

onRestoreInstanceState(Bundle savedInstanceState)只有在activity確實是被系統回收,重新創建activity的情況下才會被呼叫,

1.2.2.1.螢屏方向切換時,activity生命周期如下

onPause -> onSaveInstanceState -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume

1.2.2.2.在后臺被回收

1.2.2.3.按HOME鍵回傳桌面,又馬上點擊應用圖示回到原來頁面時不會被回收

onStart -> onRestoreInstanceState -> onResume

1.2.3原始碼

系統會呼叫ActivityThread的performStopActivity方法中掉用onSaveInstanceState, 將狀態保存在mActivities中,mActivities維護了一個Activity的資訊表,當Activity重啟時候,會從mActivities中查詢到對應的ActivityClientRecord,

如果有資訊,則呼叫Activity的onResoreInstanceState方法,

在ActivityThread的performLaunchActivity方法中,統會判斷ActivityClientRecord物件的state是否為空

不為空則通過Activity的onSaveInstanceState獲取其UI狀態資訊,通過這些資訊傳遞給Activity的onCreate方法,

1.3.activity的啟動模式和使用場景

1.3.1 android任務堆疊

我們每次打開一個新的Activity或者退出當前Activity都會在一個稱為任務堆疊的結構中添加或者減少一個Activity組件,一個任務堆疊包含了一個activity的集合,

android通過ActivityRecord、TaskRecord、ActivityStack,ActivityStackSupervisor,ProcessRecord有序地管理每個activity,

1.3.2 Standard

默認模式,每次啟動Activity都會創建一個新的Activity實體,

1.3.3 SingleTop

通知訊息打開的頁面

如果要啟動的Activity已經在堆疊頂,則不會重新創建Activity,只會呼叫該該Activity的onNewIntent()方法,

如果要啟動的Activity不在堆疊頂,則會重新創建該Activity的實體,

1.3.4 SingleTask

主界面

如果要啟動的Activity已經存在于它想要歸屬的堆疊中,那么不會創建該Activity實體,將堆疊中位于該Activity上的所有的Activity出堆疊,同時該Activity的onNewIntent()方法會被呼叫,

1.3.5SingleInstance

呼叫來電界面

要創建在一個新堆疊,然后創建該Activity實體并壓入新堆疊中,新堆疊中只會存在這一個Activity實體,

1.4.Activity A跳轉Activity B,再按回傳鍵,生命周期執行的順序

在A跳轉B會執行:A onPause -> B onCreate -> B onStart -> B onResume->A onStop

在B按下回傳鍵會執行:B onPause -> A onRestart -> A onStart -> A onResume-> B onStop -> B onDestroy

當A跳轉到B的時候,A先執行onPause,然后居然是B再執行onCreate -> onStart -> onResume,最后才執行A的onStop!!!

當B按下回傳鍵,B先執行onPause,然后居然是A再執行onRestart -> onStart -> onResume,最后才是B執行onStop -> onDestroy!!!

當 B Activity 的 launchMode 為 singleInstance,singleTask 且對應的 B Activity 有可復用的實體時,生命周期回呼是這樣的:

A.onPause -> B.onNewIntent -> B.onRestart -> B.onStart -> B.onResume -> A.onStop -> ( 如果 A 被移出堆疊的話還有一個 A.onDestory)

當 B Activity 的 launchMode 為 singleTop且 B Activity 已經在堆疊頂時(一些特殊情況如通知欄點擊、連點),此時只有 B 頁面自己有生命周期變化:

B.onPause -> B.onNewIntent -> B.onResume

1.5.橫豎屏切換,按home鍵,按回傳鍵,鎖屏與解鎖螢屏,跳轉透明Activity界面,啟動一個 Theme 為 Dialog 的 Activity,彈出Dialog時Activity的生命周期

橫豎屏切換

從 Android 3.2 (API級別 13)開始

1、不設定Activity的androidconfigChanges,或設定Activity的androidconfigChanges=“orientation”,或設定Activity的android:configChanges=“orientation|keyboardHidden”,切屏會重新呼叫各個生命周期,切橫屏時會執行一次,切豎屏時會執行一次,

2、配置 android:configChanges=“orientation|keyboardHidden|screenSize”,才不會銷毀 activity,且只呼叫 onConfigurationChanged方法,

豎屏:

啟動:onCreat->onStart->onResume.

切換橫屏時:

onPause-> onSaveInstanceState ->onStop->onDestory

onCreat->onStart->onSaveInstanceState->onResume.

如果配置這個屬性:androidconfigChanges=“orientation|keyboardHidden|screenSize”

就不會在呼叫Activity的生命周期,只會呼叫onConfigurationChanged方法

HOME鍵的執行順序:onPause->onStop->onRestart->onStart->onResume

BACK鍵的順序: onPause->onStop->onDestroy->onCreate->onStart->onResume

鎖屏:鎖屏時只會呼叫onPause(),而不會呼叫onStop方法,開屏后則呼叫onResume(),

彈出 Dialog: 直接是通過 WindowManager.addView 顯示的(沒有經過 AMS),所以不會對生命周期有任何影響,

啟動theme為DialogActivity,跳轉透明Activity

A.onPause -> B.onCrete -> B.onStart -> B.onResume

( Activity 不會回呼 onStop,因為只有在 Activity 切到后臺不可見才會回呼 onStop)

1.6.onStart 和 onResume、onPause 和 onStop 的區別

onStart 和 onResume 從 Activity 可見可互動區分

onStart 用戶可以看到部分activity但不能與它互動 onResume()可以獲得activity的焦點,能夠與用戶互動

onStop 和 onPause 從 Activity 是否位于前臺,是否有焦點區分

onPause表示當前頁面失去焦點,

onStop表示當前頁面不可見,

dialog的主題頁面,這個時候,打開著一個頁面,就只會執行onPause,而不會執行onStop,

1.7.Activity之間傳遞資料的方式Intent是否有大小限制,如果傳遞的資料量偏大,有哪些方案

startActivity->startActivityForResult->Instrumentation.execStartActivity

->ActivityManger.getService().startActivity

intent中攜帶的資料要從APP行程傳輸到AMS行程,再由AMS行程傳輸到目標Activity所在行程

通過Binder來實作行程間通信

1.Binder 驅動在內核空間創建一個資料接收快取區,

2.在內核空間開辟一塊內核快取區,建立內核快取區和內核空間的資料接收快取區之間的映射關系,以及內核中資料接收快取區和接收行程用戶空間地址的映射關系,

3.發送方行程通過系統呼叫 copyfromuser() 將資料 copy 到內核空間的內核快取區,由于內核快取區和接收行程的用戶空間存在記憶體映射,因此也就相當于把資料發送到了接收行程的用戶空間,這樣便完成了一次行程間的通信,

為當使用Intent來傳遞資料時,用到了Binder機制,資料就存放在了Binder的事務緩沖區里面,而事務緩沖區是有大小限制的,普通的由Zygote范訓而來的用戶行程,映射的Binder記憶體大小是不到1M的

Binder 本身就是為了行程間頻繁-靈活的通信所設計的, 并不是為了拷貝大量資料

如果非 ipc

單例,eventBus,Application,sqlite、shared preference、file 都可以;

如果是 ipc

1.共享記憶體性能還不錯, 通過 MemoryFile 開辟記憶體空間,獲得 FileDescriptor; 將 FileDescriptor 傳遞給其他行程; 往共享記憶體寫入資料; 從共享記憶體讀取資料,

2.Socket或者管道性能不太好,涉及到至少兩次拷貝,

1.8.Activity的onNewIntent()方法什么時候執行

果IntentActivity處于任務堆疊的頂端,也就是說之前打開過的Activity,現在處于onPause、onStop 狀態的話,其他應用再發送Intent的話,執行順序為:onNewIntent,onRestart,onStart,onResume,

ActivityA已經啟動過,處于當前應用的Activity堆疊中;

當ActivityA的LaunchMode為SingleTop時,如果ActivityA在堆疊頂,且現在要再啟動ActivityA,這時會呼叫onNewIntent()方法;

當ActivityA的LaunchMode為SingleInstance,SingleTask時,如果已經ActivityA已經在堆疊中,那么此時再次啟動會呼叫onNewIntent()方法;

1.9.顯示啟動和隱式啟動

顯示啟動

1、構造方法傳入Component,最常用的方式

2、setComponent(componentName)方法

3、setClass/setClassName方法

隱式啟動

隱式Intent是通過在AndroidManifest檔案中設定action、data、category,讓系統來篩選出合適的Activity

action的匹配規則

Intent-filter action可以設定多條

intent中的action只要與intent-filter其中的一條匹配成功即可,且intent中action最多只有一條

Intent-filter內必須至少包含一個action,

category的匹配規則

Intent-filter內必須至少包含一個category,android:name為android.intent.category.DEFAULT,

intent-filter中,category可以有多條

intent中,category也可以有多條

intent中所有的category都可以在intent-filter中找到一樣的(包括大小寫)才算匹配成功

data的匹配規則

intent-filter中可以設定多個data

intent中只能設定一個data

intent-filter中指定了data,intent中就要指定其中的一個data

1.10.scheme使用場景,協議格式,如何使用

scheme是一種頁面內跳轉協議,是一種非常好的實作機制,通過定義自己的scheme協議,可以非常方便跳轉app中的各個頁面

APP根據URL跳轉到另外一個APP指定頁面

可以通過h5頁面跳轉app原生頁面

服務器可以定制化跳轉app頁面

Scheme鏈接格式樣式

樣式scheme://host/path?query

Uri.parse(“hr://test:8080/goods?goodsId=8897&name=test”)

hr代表Scheme協議名稱

test代表Scheme作用的地址域

8080代表改路徑的埠號

/goods代表的是指定頁面(路徑)

goodsId和name代表傳遞的兩個引數

使用

<intent-filter>
            <!-- 協議部分配置 ,注意需要跟web配置相同-->
            <!--協議部分,隨便設定 hr://test:8080/goods?name=test  -->
            <data android:scheme="hr"
                     android:host="test"
                     android:path="/goods"
                     android:port="8080"/>
                 <!--下面這幾行也必須得設定-->
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <action android:name="android.intent.action.VIEW" />
       </intent-filter>

掉用

Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("hr://test:8080/goods?name=test"));

startActivity(intent);

1.11.ANR 的四種場景

ANR 的四種場景:

Service TimeOut: service 未在規定時間執行完成:前臺服務 20s,后臺 200s

BroadCastQueue TimeOut: 未在規定時間內未處理完廣播:前臺廣播 10s 內, 后臺 60s 內

ContentProvider TimeOut: publish 在 10s 內沒有完成

Input Dispatching timeout: 5s 內未回應鍵盤輸入、觸摸螢屏等事件

我們可以看到, Activity 的生命周期回呼的阻塞并不在觸發 ANR 的場景里面,所以并不會直接觸發 ANR,

只不過死回圈阻塞了主執行緒,如果系統再有上述的四種事件發生,就無法在相應的時間內處理從而觸發 ANR,

1.12.onCreate和onRestoreInstance方法中恢復資料時的區別

onSaveInstanceState 不一定會被呼叫,因為它只有在上次activity被回收了才會呼叫,

onCreate()里的Bundle引數可能為空,一定要做非空判斷, 而onRestoreInstanceState的Bundle引數一定不會是空值,

1.13.activty間傳遞資料的方式

通過 Intent 傳遞(Intent.putExtra 的內部也是維護的一個 Bundle,因此,通過 putExtra 放入的 資料,取出時也可以通過 Bundle 去取)

通過全域變數傳遞

通過 SharedPreferences 傳遞

通過資料庫傳遞

通過檔案傳遞

1.14.跨App啟動Activity的方式,注意事項

使用intentFilter(隱式跳轉)

在Manifest的Activity標簽中添加:

啟動時:startActivity(new Intent(“com.example.test.action.BActivity”))

如果有兩個action屬性值相同的Activity,那么在啟動時手機系統會讓你選擇啟動哪一個Activity

要解決這個問題,需要給被啟動的Activity再加上一個屬性,

然后再啟動該Activity的Intent中加上一個URI,其中“app”必須與data屬性的scheme的值一樣,

intent=new Intent(“com.zs.appb.intent.action.BeStartActivity”, Uri.parse(“app://hello”));

共享uid的App

android中uid用于標識一個應用程式,uid在應用安裝時被分配,并且在應用存在于手機上期間,都不會改變,一個應用程式只能有一個uid,多個應用可以使用sharedUserId 方式共享同一個uid,前提是這些應用的簽名要相同,

在AndroidManifest中:manifest標簽中添加android:sharedUserId=“xxxx”

啟動時:startActivity(new Intent().setComponent(new ComponentName(“com.example.test”,“com.example.test.XxxActivity”)));

使用exported

一旦設定了intentFilter之后,exported就默認被設定為true了

在Manifest中添加exported屬性

啟動時:startActivity(new Intent().setComponent(new ComponentName(“com.example.zhu”,“com.example.zhu.XxxActivity”)));

注意(如何防止自己的Activity被外部非正常啟動):

如果AppB設定了android:permission=”xxx.xxx.xx”那么, 就必須在你的AppA的AndroidManifast.xml中uses-permission xxx.xxx.xx才能訪問人家的東西,

給AppA的manifest中添加權限:

gei AppB中需要啟動的Activity添加permission屬性:

android:permission=“com.example.test”

1.15.Activity任務堆疊是什么

1.android任務堆疊又稱為Task,它是一個堆疊結構,具有后進先出的特性,用于存放我們的Activity組件,

2.我們每次打開一個新的Activity或者退出當前Activity都會在一個稱為任務堆疊的結構中添加或者減少一個Activity組件, 一個任務堆疊包含了一個activity的集合, 只有在任務堆疊堆疊頂的activity才可以跟用戶進行互動,

3.在我們退出應用程式時,必須把所有的任務堆疊中所有的activity清除出堆疊時,任務堆疊才會被銷毀,當然任務堆疊也可以移動到后臺, 并且保留了每一個activity的狀態. 可以有序的給用戶列出它們的任務, 同時也不會丟失Activity的狀態資訊,

4.對應AMS中的ActivityRecord、TaskRecord、ActivityStack(AMS中的總結)

1.16.有哪些Activity常用的標記位Flags

FLAG_ACTIVITY_NEW_TASK

此標記位作用是為Activity指定“singleTask”啟動模式,其效果和在XML中指定相同android:launchMode=“singleTask”

FLAG_ACTIVITY_SINGLE_TOP

此標記位作用是為Activity指定“singleTop”啟動模式,其效果和在XML中指定相同android:launchMode=“singleTop”

FLAG_ACTIVITY_CLEAR_TOP

具有此標記位的Activity,當它啟動時,在同一個任務堆疊中位于它上面的Activity都要出堆疊,此標記位一般會和singleTask啟動模式一起出現,此情況下,若被啟動的Activity實體存在,則系統會呼叫它的onNewIntent,

1.17.Activity的資料是怎么保存的,行程被Kill后,保存的資料怎么恢復的

在Activity的onSaveInstanceState方法回呼時,put到引數outState(Bundle)里面,outState就是ActivityClientRecord的state,

ActivityClientRecord實體,都存放在ActivityThread的mActivities里面,

Activity變得不可見時(onSaveInstanceState和onStop回呼之后),在應用行程這邊會通過ActivityTaskManagerService的activityStopped方法,把剛剛在onSaveInstanceState中滿載了資料的Bundle物件,傳到系統服務行程那邊! 然后(在系統服務行程這邊),會進一步將這個Bundle物件,賦值到對應ActivityRecord的icicle上

ActivityRecord是用來記錄對應Activity的各種資訊的,如theme,啟動模式、當前是否可見等等(為了排版更簡潔,上圖只列出來一個icicle),它里面還有很多管理Activity狀態的相關方法;

TaskRecord就是大家耳熟能詳的任務堆疊(從上圖可以看出并不真的是堆疊)了,它的主要職責就是管理ActivityRecord,每當Activity啟動時,會先找到合適的TaskRecord(或創建新實體),然后將該Activity所對應的ActivityRecord添加到TaskRecord的mActivities中;

ActivityStack管理著TaskRecord,當新TaskRecord被創建后,會被添加到它mTaskHistory里面,

2.Service

2.1.service 的生命周期,兩種啟動方式的區別

startService

onCreate() -> onStartCommand() -> onDestroy()

bindService

onCreate() -> onbind() -> onUnbind()-> onDestroy()

區別

啟動

如果服務已經開啟,多次執行startService不會重復的執行onCreate(), 而是會呼叫onStart()和onStartCommand(),

如果服務已經開啟,多次執行bindService時,onCreate和onBind方法并不會被多次呼叫

銷毀

當執行stopService時,直接呼叫onDestroy方法

呼叫者呼叫unbindService方法或者呼叫者Context不存在了(如Activity被finish了),Service就會呼叫onUnbind->onDestroy

使用startService()方法啟用服務,呼叫者與服務之間沒有關連,即使呼叫者退出了,服 務仍然運行,

使用bindService()方法啟用服務,呼叫者與服務系結在了一起,呼叫者一旦退出,服務也就終止,

1、單獨使用startService & stopService

(1)第一次呼叫startService會執行onCreate、onStartCommand,

(2)之后再多次呼叫startService只執行onStartCommand,不再執行onCreate,

(3)呼叫stopService會執行onDestroy,

2、單獨使用bindService & unbindService

(1)第一次呼叫bindService會執行onCreate、onBind,

(2)之后再多次呼叫bindService不會再執行onCreate和onBind,

(3)呼叫unbindService會執行onUnbind、onDestroy,

2.2.Service啟動流程

1.Process A行程采用Binder IPC向system_server行程發起startService請求;

2.system_server行程接收到請求后,向zygote行程發送創建行程的請求;

3.zygote行程fork出新的子行程Remote Service行程;

4.Remote Service行程,通過Binder IPC向sytem_server行程發起attachApplication請求;

5.system_server行程在收到請求后,進行一系列準備作業后,再通過binder IPC向remote Service行程發送scheduleCreateService請求;

6.Remote Service行程的binder執行緒在收到請求后,通過handler向主執行緒發送CREATE_SERVICE訊息;

7.主執行緒在收到Message后,通過發射機制創建目標Service,并回呼Service.onCreate()方法,

到此,服務便正式啟動完成,當創建的是本地服務或者服務所屬行程已創建時,則無需經過上述步驟2、3,直接創建服務即可,

bindService

startService

2.3.Service與Activity怎么實作通信

通過Binder物件

1.Service中添加一個繼承Binder的內部類,并添加相應的邏輯方法

2.Service中重寫Service的onBind方法,回傳我們剛剛定義的那個內部類實體

3.Activity中系結服務,重寫ServiceConnection,onServiceConnected時回傳的IBinder(Service中的binder)呼叫邏輯方法

Service通過BroadCast廣播與Activity通信

2.4.IntentService是什么,IntentService原理,應用場景及其與Service的區別

what

IntentService 是 Service 的子類,默認開啟了一個作業執行緒HandlerThread,使用這個作業執行緒逐一處理所有啟動請求,在任務執行完畢后會自動停止服務,只要實作一個方法 onHandleIntent,該方法會接收每個啟動請求的 Intent,能夠執行后臺作業和耗時操作,

可以啟動 IntentService 多次,而每一個耗時操作會以佇列的方式在 IntentService 的 onHandlerIntent 回呼方法中執行,并且,每一次只會執行一個作業執行緒,執行完第一個再執行第二個,并且等待所有訊息都執行完后才終止服務,

how

1.創建一個名叫 ServiceHandler 的內部 Handler

2.把內部Handler與HandlerThread所對應的子執行緒進行系結

3.HandlerThread開啟執行緒 創建自己的looper

4.通過 onStartCommand() intent,依次插入到作業佇列中,并發送給 onHandleIntent()逐個處理

可以用作后臺下載任務 靜默上傳

why IntentService會創建獨立的worker執行緒來處理所有的Intent請求 Service主執行緒不能處理耗時操作,IntentService不會阻塞UI執行緒,而普通Serveice會導致ANR例外,

為Service的onBind()提供默認實作,回傳null;onStartCommand提供默認實作,將請求Intent添加到佇列中,

所有請求處理完成后,IntentService會自動停止,無需呼叫stopSelf()方法停止Service,

2.5.Service 的 onStartCommand 方法有幾種回傳值?各代表什么意思?

START_NOT_STICKY

在執行完 onStartCommand 后,服務被例外 kill 掉,系統不會自動重啟該服務,

START_STICKY

重傳 Intent,使用這個回傳值時,如果在執行完 onStartCommand 后,服務被異 常 kill 掉,系統會自動重啟該服務 ,并且onStartCommand方法會執行,onStartCommand方法中的intent值為null,

適用于媒體播放器或類似服務,

START_REDELIVER_INTEN

使用這個回傳值時,服務被異 常 kill 掉,系統會自動重啟該服務,并將 Intent 的值傳入,

適用于主動執行應該立即恢復的作業(例如下載檔案)的服務,

2.6.bindService和startService混合使用的生命周期以及怎么關閉

如果你只是想要啟動一個后臺服務長期進行某項任務,那么使用startService便可以了,如果你還想要與正在運行的Service取得聯系,那么有兩種方法:一種是使用broadcast,另一種是使用bindService,

如果先startService,再bindService

onCreate() -> onbind() -> onStartCommand()

如果先bindService,再startService

onCreate() -> onStartCommand() -> onbind()

如果只stopService

Service的OnDestroy()方法不會立即執行,在Activity退出的時候,會執行OnDestroy,

如果只unbindService

只有onUnbind方法會執行,onDestory不會執行

如果要完全退出Service,那么就得執行unbindService()以及stopService,

3.BroadcastReceiver

3.1.廣播的分類和使用場景

Android 廣播分為兩個角色:廣播發送者、廣播接受者

廣播接收器的注冊分為兩種:靜態注冊、動態注冊,

靜態廣播接收者:通過AndroidManifest.xml的標簽來申明的BroadcastReceiver,

動態廣播接收者:通過AMS.registerReceiver()方式注冊的BroadcastReceiver,動態注冊更為靈活,可在不需要時通過unregisterReceiver()取消注冊,

廣播型別:根據廣播的發送方式,

1.普通廣播:通過Context.sendBroadcast()發送,可并行處理

2.系統廣播:當使用系統廣播時,只需在注冊廣播接收者時定義相關的action即可,不需要手動發送廣播(網路變化,鎖屏,飛行模式)

3.有序廣播: 指的是發送出去的廣播被 BroadcastReceiver 按照先后順序進行接收 發送方式變為:sendOrderedBroadcast(intent);

廣播接受者接收廣播的順序規則(同時面向靜態和動態注冊的廣播接受者):按照 Priority 屬性值從大-小排序,Priority屬性相同者,動態注冊的廣播優先,

4.App應用內廣播(Local Broadcast)

背景 Android中的廣播可以跨App直接通信(exported對于有intent-filter情況下默認值為true)

沖突 可能出現的問題:

其他App針對性發出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收廣播并處理;

其他App注冊與當前App一致的intent-filter用于接收廣播,獲取廣播具體資訊; 即會出現安全性 & 效率性的問題,

解決方案 使用App應用內廣播(Local Broadcast)

App應用內廣播可理解為一種區域廣播,廣播的發送者和接收者都同屬于一個App, 相比于全域廣播(普通廣播),App應用內廣播優勢體現在:安全性高 & 效率高

具體使用1 - 將全域廣播設定成區域廣播

注冊廣播時將exported屬性設定為false,使得非本App內部發出的此廣播不被接收; 在廣播發送和接收時,增設相應權限permission,用于權限驗證;

發送廣播時指定該廣播接收器所在的包名,此廣播將只會發送到此包中的App內與之相匹配的有效廣播接收器中,

具體使用2 - 使用封裝好的LocalBroadcastManager類

對于LocalBroadcastManage,方式發送的應用內廣播,只能通過LocalBroadcastManager動態注冊,不能靜態注冊

5.粘性廣播(Sticky Broadcast) 由于在Android5.0 & API 21中已經失效,所以不建議使用,在這里也不作過多的總結,

應用場景

同一 App 內部的不同組件之間的訊息通信(單個行程);

不同 App 之間的組件之間訊息通信;

Android系統在特定情況下與App之間的訊息通信,如:網路變化、電池電量、螢屏開關等,

3.2.廣播的兩種注冊方式的區別

靜態注冊:常駐系統,不受組件生命周期影響,即便應用退出,廣播還是可以被接收,耗電、占記憶體,

動態注冊:非常駐,跟隨組件的生命變化,組件結束,廣播結束,在組件結束前,需要先移除廣播,否則容易造成記憶體泄漏,

3.3.廣播發送和接收的原理

動態注冊

1.創建物件LoadedApk.ReceiverDispatcher.InnerReceiver的實體,該物件繼承于IIntentReceiver.Stub(InnerReceiver實際是一個binder本地物件(BBinder:本地Binder,服務實作方的基類,提供了onTransact介面來接收請求)),

2.將IIntentReceiver物件和注冊所傳的IntentFilter物件發送給AMS, AMS記錄IIntentReceiver、IntentFilter和注冊的行程ProcessRecord,并建立起它們的對應關系,

3.當有廣播發出時,AMS根據廣播intent所攜帶的IntentFilter找到IIntentReceiver和ProcessRecord,然后回呼App的ApplicationThread物件的scheduleRegisteredReceiver,將IIntentReceiver和廣播的intent一并傳給App,App直接呼叫IIntentReceiver的performReceive,

4.因為廣播是通過binder執行緒回呼到接收行程的,接收行程通過ActivityThread里的H這個Handler將呼叫轉到主執行緒,然后回呼BroadcastReceiver的onReceive,

靜態注冊

靜態注冊是通過在Manifest檔案中宣告實作了BroadcastReceiver的自定義類和對應的IntentFilter,來告訴PMS(PackageManagerService)這個App所注冊的廣播,

當AMS接收到廣播后,會查找所有動態注冊的和靜態注冊的廣播接收器,靜態注冊的廣播接收器是通過PMS(PackageManagerService)發現的,PMS找到對應的App

對應行程已經創建,直接呼叫App的ApplicationThread物件的scheduleReceiver

對應行程尚未創建,先啟動App行程,App行程啟動后回呼AMS的attachApplication,attachApplication則繼續派發剛才的廣播App這邊收到呼叫后會先通過Handler轉到主執行緒,然后根據AMS傳過來的引數實體化廣播接收器的類,接著呼叫廣播接收器的onReceive,

3.4.本地廣播和全域廣播的區別

BroadcastReceiver是針對應用間、應用與系統間、應用內部進行通信的一種方式

LocalBroadcastReceiver僅在自己的應用內發送接收廣播,也就是只有自己的應用能收到,資料更加安全廣播只在這個程式里,而且效率更高,

BroadcastReceiver采用的binder方式實作跨行程間的通信;

LocalBroadcastManager使用Handler通信機制,

LocalBroadcastReceiver 使用

LocalBroadcastReceiver不能靜態注冊,只能采用動態注冊的方式,

在發送和注冊的時候采用,LocalBroadcastManager的sendBroadcast方法和registerReceiver方法

注冊程序,主要是向mReceivers和mActions添加相應資料:

mReceivers:資料型別為HashMap<BroadcastReceiver, ArrayList>, 記錄廣播接收者與IntentFilter串列的對應關系;

mActions:資料型別為HashMap<String, ArrayList>, 記錄action與廣播接收者的對應關系

根據Intent的action來查詢相應的廣播接收者串列;

發送MSG_EXEC_PENDING_BROADCASTS訊息,回呼相應廣播接收者的onReceive方法

由于內容實在太多了,在這里就不方便做全部的展示,以上就是《Android高級開發面試題2.0》的部分,需要的小伙伴可以一鍵三連(點贊+收藏+關注)后直接+加V:lx5888888888838 或者【點擊這里直達免費獲取方式!

寫在最后

我個人覺得面試也像是一場全新的征程,失敗和勝利都是平常之事,所以,勸各位不要因為面試失敗而灰心、喪失斗志,也不要因為面試通過而沾沾自喜,等待你的將是更美好的未來,繼續加油!

—————祝各位前程似錦,offer不斷!!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/292385.html

標籤:其他

上一篇:Android開發:從來沒不做性能優化,你憑什么跟我說 “這個行業太卷了!”

下一篇:Android開發、adb、monkey測驗

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more