Android四大組件學習總結

?1. Activity 啟動模式問題?

?面試官?:
“我看你項目里用了 SingleTask 模式,能具體說說為什么用它嗎?如果從 Activity A(SingleTask)跳轉到 B(Standard),再返回 A,任務棧會怎么變化?”

?候選人?:
技巧?:先明確問題,再分場景解釋)
“好的。在我們的項目里,主頁 Activity 被設置為 SingleTask 模式,主要是為了防止重復創建主頁。比如用戶從通知欄跳轉到主頁時,如果已經有主頁實例在后臺,就直接復用,而不是新建一個,這樣可以避免用戶按返回鍵時多次退出。

您提到的從 A 跳轉到 B 再返回 A 的情況,假設 A 是 SingleTask,B 是 Standard:

  1. 當第一次啟動 A 時,系統會為 A 創建一個獨立的任務棧,假設叫 Task1。
  2. 從 A 跳轉 B,因為 B 是 Standard 模式,B 會被壓入 Task1 的棧頂。
  3. 當從 B 返回 A 時,由于 A 是 SingleTask,系統會先檢查任務棧。發現 Task1 中已經存在 A 實例,于是會把 A 之上的所有 Activity(也就是 B)彈出棧,讓 A 回到棧頂。這時候用戶再按返回鍵,就直接退出應用了。”

?加分話術?:
“這里有個實際踩過的坑:如果 A 的啟動模式設置不當,可能會導致返回棧混亂。我們當時用 adb shell dumpsys activity 命令查看任務棧,驗證邏輯是否符合預期。”


?2. Service 保活與 ANR 問題?

?面試官?:
“Service 里做耗時操作為什么會 ANR?你們項目里怎么解決的?”

?候選人?:
技巧?:承認問題 + 解決方案 + 實際案例)
“是的,Service 默認運行在主線程,如果直接在里面做網絡請求或大量計算,肯定會阻塞主線程導致 ANR。我們在項目里是這樣處理的:

  1. ?異步處理?:比如用 IntentService,它內部自己開了工作線程,處理完自動停止。
  2. ?結合 HandlerThread?:如果是長期運行的后臺任務,會創建一個 HandlerThread,再通過 Handler 發送任務到子線程執行。
  3. ?前臺服務保活?:像音樂播放功能,我們用了前臺服務,顯示通知欄避免被系統回收。不過保活很難完全做到,Android 8.0 之后限制更多,我們最終改用 JobScheduler 在合適時機重啟服務。”

?加分話術?:
“其實現在更推薦用 WorkManager 處理后臺任務,它能根據系統版本自動選擇底層實現,比如用 JobScheduler 或 AlarmManager,這樣兼容性更好。”

Service 擴展?

?場景一:Service 混合啟動模式?

?面試官?:
“假設我先用 startService() 啟動了一個 Service,接著又用 bindService() 綁定它。這時候 Service 的生命周期會怎么走?銷毀時要注意什么?”

?候選人?:
自然思考狀
“嗯,這個問題其實涉及到 Service 的兩種啟動方式混合使用的情況。我舉個例子吧:比如我們做一個音樂播放器,先用 startService() 啟動播放服務,保證音樂在后臺持續播放;然后在 Activity 里調用 bindService() 綁定它,用來調節音量或者切歌。這時候 Service 的生命周期大概是這樣的——”

  1. ?第一步?:startService() 觸發后,Service 會先走 onCreate(),然后 onStartCommand(),這時候服務就算正式啟動了。
  2. ?第二步?:再調用 bindService(),這時候不會重新創建 Service,而是直接調用 onBind(),返回一個 IBinder 對象給客戶端。
  3. ?銷毀時?:得同時解綁和停止服務。比如用戶退出 Activity 時調用 unbindService(),然后還得主動調用 stopService(),否則 Service 會一直活著,直到系統資源不足被干掉。”

加分話術?:
“在源碼中,Service 的生命周期由?ActivityManagerService?管理。每次?startService()?會增加一個 ‘started’ 狀態計數,而?bindService()?會增加一個 ‘bound’ 計數。只有當兩個計數都歸零時,才會調用?onDestroy()。我們可以通過?adb shell dumpsys activity services?查看當前 Service 的狀態。”?

補充踩坑經驗
“對了,我之前遇到過這種情況:只調了 unbindService() 沒調 stopService(),結果發現通知欄的音樂控件還在,用戶點了之后又恢復播放。后來用 adb shell dumpsys activity services 一查,發現 Service 的 ‘started’ 狀態還沒歸零,這才恍然大悟。”


?場景二:IntentService 的線程模型?

?面試官?:
“IntentService 是怎么在子線程處理任務的?如果我連續發 10 個 Intent,它們是排隊一個一個執行,還是能并發?”

?候選人?:
????????這個問題我當初也好奇,還特意寫代碼驗證過。IntentService 內部其實藏了個 HandlerThread,這個類特別有意思,它自己帶了一個 Looper,專門用來在子線程處理消息隊列。
? ? ? ? 當您調用 startService() 發送 Intent 時,IntentService 會把每個 Intent 包裝成一個 Message,扔進 HandlerThread 的消息隊列里。這個隊列是先進先出的,所以哪怕同時發 10 個 Intent,也得老老實實排隊。比如第一個任務是下載文件,耗時 5 秒,后面 9 個任務都得等它完了才能執行。

舉反例
“不過有一次,我手賤在 onHandleIntent() 里開了個新線程,結果任務全并行跑起來了,日志亂成一團。這才明白:IntentService 的串行特性全靠 HandlerThread 的消息隊列,如果自己開線程反而會打破這個機制。”


?場景三:Service 的 ANR 避坑?

?面試官?:
“聽說在 Service 里直接做網絡請求會 ANR?你們項目里是怎么處理的?”

?候選人?:
“這事兒我們還真踩過坑!早期圖省事,在 onStartCommand() 里直接寫了個網絡請求,結果線上 ANR 率飆升。后來復盤發現,Service 默認在主線程跑,一個慢請求就能卡死整個 APP。”

分步驟解釋
“我們的解決方案分了三步走:

  1. ?緊急修復?:先在 onStartCommand() 里手動 new Thread(),把請求扔到子線程。雖然土,但能快速止血。
  2. ?中期優化?:換成 IntentService,但很快就發現它只能串行執行,下個版本需求要支持多文件同時上傳,只好再改。
  3. ?最終方案?:上線程池!用 Executors.newFixedThreadPool(3) 控制并發數,搭配 LiveData 把結果拋回主線程更新 UI。代碼大概是這樣的——”

模擬寫代碼

public class UploadService extends Service {private ExecutorService pool = Executors.newFixedThreadPool(3);@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {pool.execute(() -> {String url = intent.getStringExtra("url");boolean success = doUpload(url); // 模擬上傳LiveDataBus.getInstance().post(new UploadEvent(success));});return START_NOT_STICKY;}
}

?場景四:IntentService 的淘汰原因?

?面試官?:
“聽說 IntentService 過時了?你們現在用什么替代?”

?候選人?:
“確實,Android 8.0 之后 IntentService 有點力不從心了。比如我們之前用它做日志上報,結果在后臺經常被系統干掉,查文檔才發現:8.0 開始限制后臺 Service,startService() 得配合前臺通知才能用。”

對比分析
“后來我們全面轉向 WorkManager,這玩意兒聰明在哪呢?它底層自動適配系統版本——在 Android 6.0 用 AlarmManager,7.0 用 JobScheduler,甚至還能在國產 ROM 上兼容。比如上傳失敗的任務會自動重試,還能設置網絡條件,比 IntentService 手動重試省心多了。”

舉例說明
“比如一個夜間日志上傳的需求,用 WorkManager 可以這么搞:”

// 定義任務
class LogUploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {override fun doWork(): Result {return if (uploadLogs()) Result.success() else Result.retry()}
}// 設置約束:充電狀態 + 夜間時段
val constraints = Constraints.Builder().setRequiresCharging(true).build()val request = OneTimeWorkRequestBuilder<LogUploadWorker>().setConstraints(constraints).setInitialDelay(6, TimeUnit.HOURS) // 延遲到凌晨.build()WorkManager.getInstance(context).enqueue(request)

“現在除非兼容老系統,否則新項目基本不用 IntentService 了。不過它的設計思想——子線程干活、干完自毀,在 WorkManager 的 Worker 里還能看到影子。”


?3. BroadcastReceiver 使用場景?

?面試官?:
“你提到用廣播實現登錄狀態同步,能具體說說嗎?靜態注冊和動態注冊怎么選?”

?候選人?:
技巧?:場景化描述 + 安全提醒)
“比如用戶登錄成功后,我們需要更新多個頁面的 UI。這時候發送一個自定義廣播,各個頁面注冊 Receiver 監聽。登錄頁發送廣播后,主頁、個人中心頁收到通知,主動刷新數據。

關于注冊方式的選擇:

  • ?靜態注冊?:適合監聽系統廣播,比如開機啟動。但要注意 Android 8.0 之后對靜態廣播的限制。
  • ?動態注冊?:靈活且優先級高,但要在 Activity 或 Fragment 的 onResume 注冊,onPause 注銷,防止內存泄漏。

不過現在更推薦用 LiveData 或 EventBus 替代廣播,減少系統開銷。只有跨進程通信時才會用 ContentProvider 或廣播。”

?加分話術?:
“我們之前遇到過一個坑:動態注冊的 Receiver 沒及時注銷,導致 Activity 泄漏。后來用 LeakCanary 檢測出來,加了個 try-catch 確保 unregisterReceiver 一定執行。”


?4. ContentProvider 安全與多進程?

?面試官?:
“如果想讓其他應用訪問我們的數據,用 ContentProvider 怎么保證安全?”

?候選人?:
技巧?:分層回答 + 權限細節)
“我們分了三層防護:

  1. ?權限聲明?:在 AndroidManifest.xml 里定義讀寫權限,比如 com.example.READ_DATA,并設置 protectionLevel="signature",只允許相同簽名的應用訪問。
  2. ?Uri 權限控制?:在 Provider 的 query 方法里校驗調用方的包名,通過 Binder.getCallingUid() 獲取 UID,對比白名單。
  3. ?數據加密?:敏感數據(如用戶手機號)在存儲時用 AES 加密,即使被惡意讀取也無法解密。”

?加分話術?:
“其實 Android 的 FileProvider 也是類似的思路,通過 grantUriPermission 動態授權臨時權限,避免長期暴露數據。”


基礎知識講解

?Activity 啟動模式(LaunchMode)及場景?
  • ?Standard?:默認模式,每次啟動創建新實例(可能產生重復登錄頁面的問題)。
  • ?SingleTop?:棧頂復用,若已在棧頂則不創建新實例(適用于通知跳轉頁)。
  • ?SingleTask?:棧內復用,在任務棧中只存在一個實例(主頁面常用)。
  • ?SingleInstance?:獨立任務棧,全局唯一(如系統來電頁面)。

?真題?:
?Q?:從 Activity A(SingleTask)跳轉到 B(Standard),再從 B 跳轉回 A,描述任務棧變化。
?A?:A 啟動時創建新任務棧,B 在默認棧中。當 B 跳轉回 A 時,由于 A 的 SingleTask 特性,系統會清空 A 所在棧頂之上的所有 Activity,直接復用 A 實例。


Q1:Activity A 跳轉 B,B 跳轉 C,按返回鍵時的生命周期回調順序? (假設 A, B, C 都是 Standard 模式)

A: (這是一個經典問題,關鍵在于理解 Activity 棧和生命周期)

  1. 當前狀態: 棧頂是 C,其下是 B,再下是 A。 [A, B, C]

  2. 在 C 按返回鍵:

    • C: onPause()
    • B: onRestart() (如果 B 之前 onStop() 了) -> onStart() -> onResume() (B 變為可見并獲得焦點)
    • C: onStop() -> onDestroy() (C 被銷毀并出棧)
    • 此時棧: [A, B]
  3. 在 B 按返回鍵:

    • B: onPause()
    • A: onRestart() (如果 A 之前 onStop() 了) -> onStart() -> onResume()
    • B: onStop() -> onDestroy()
    • 此時棧: [A]

?Activity 與 Fragment 通信方式?
  • ?Bundle + setArguments?:傳遞初始參數。
  • ?接口回調?:Fragment 定義接口,Activity 實現。
  • ?ViewModel?:通過共享 ViewModel 實現數據監聽。
  • ?EventBus?:事件總線解耦通信(需注意內存泄漏)。

?真題?:
?Q?:Fragment 如何回傳數據給 Activity?
?A?:在 Fragment 中定義接口,在?onAttach()?中綁定 Activity 實例,調用接口方法傳值。代碼示例:

// Fragment 中
public interface OnDataCallback {void onDataReceived(String data);
}@Override
public void onAttach(Context context) {super.onAttach(context);if (context instanceof OnDataCallback) {callback = (OnDataCallback) context;}
}// 傳值時調用
callback.onDataReceived("data");

Q1?:Activity A 跳轉 B,B 跳轉 C,按返回鍵的生命周期回調順序?
?A?:

  • C →?onPause()?→ B →?onRestart()?→?onStart()?→?onResume()?→ C →?onStop()?→?onDestroy()

?Q2?:Service 中執行耗時操作為何可能引發 ANR?如何解決?
?A?:Service 默認運行在主線程,直接執行耗時操作會阻塞 UI 線程。應使用?IntentService?或?HandlerThread?在子線程處理。

?Q3?:BroadcastReceiver 的 onReceive() 中能否啟動彈窗?
?A?:可以,但需通過?Intent?跳轉 Activity 并添加?FLAG_ACTIVITY_NEW_TASK(因為 Receiver 無任務棧)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82184.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82184.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于SamOutV8的序列生成模型實現與分析

項目概述 本項目實現了基于SamOutV8架構的序列生成模型&#xff0c;核心組件包括MaxStateSuper、FeedForward和DecoderLayer等模塊。通過結合自注意力機制與狀態編碼策略&#xff0c;該模型在處理長序列時表現出良好的性能。 核心組件解析 1. MaxStateSuper&#xff08;狀態編…

從腦電圖和大腦記錄中學習穩健的深度視覺表征

從腦電圖和大腦記錄中學習穩健的深度視覺表征 印度&#xff0c;印度&#xff0c;印度&#xff0c;印度大腦實驗室&#xff0c;印度 例如&#xff0c;達拉普&#xff0c;克普拉薩德&#xff0c;山&#xff0c;山&#xff0c;新的。ac .在 摘要 解碼人類大腦一直是新機器人科學家…

2025.5個人感悟

本人是一名2025級大四學生&#xff0c;離畢業就一個月了&#xff0c;目前論文終稿已寫完&#xff0c;有多的時間可以來寫一寫博客了。 &#xff08;1&#xff09;越焦慮什么&#xff0c;未來就有可能變成什么樣子。以前一直焦慮考不上研&#xff0c;秋招找不到工作&#xff0c…

使用騰訊云3臺輕量云服務器快速部署K8s集群實戰

一、服務器配置 1.集群數量 節點ip備注master10.0.4.9安全組放通&#xff0c;3節點內網互通node110.0.4.14安全組放通&#xff0c;3節點內網互通node210.0.4.17安全組放通&#xff0c;3節點內網互通 2.配置服務器&#xff08;每個節點執行&#xff09; 執行步驟1 #在對應的…

bitbar環境搭建(ruby 2.4 + rails 5.0.2)

此博客為武漢大學WA學院網絡安全課程&#xff0c;理論課大作業Web環境搭建。 博主搭了2天&#xff01;&#xff01;&#xff01;血淚教訓是還是不能太相信ppt上的教程。 一開始嘗試了ppt上的教程&#xff0c;然后又轉而尋找網絡資源 cs155源代碼和docker配置&#xff0c;做到…

leetcode:2469. 溫度轉換(python3解法,數學相關算法題)

難度&#xff1a;簡單 給你一個四舍五入到兩位小數的非負浮點數 celsius 來表示溫度&#xff0c;以 攝氏度&#xff08;Celsius&#xff09;為單位。 你需要將攝氏度轉換為 開氏度&#xff08;Kelvin&#xff09;和 華氏度&#xff08;Fahrenheit&#xff09;&#xff0c;并以數…

python 實現一個完整的基于Python的多視角三維重建系統,包含特征提取與匹配、相機位姿估計、三維重建、優化和可視化等功能

多視角三維重建系統 下面我將實現一個完整的基于Python的多視角三維重建系統,包含特征提取與匹配、相機位姿估計、三維重建、優化和可視化等功能。 1. 環境準備與數據加載 首先安裝必要的庫: pip install opencv-python opencv-contrib-python numpy matplotlib plotly s…

什么是國密、密評、商密

一、國密 定義與本質&#xff1a;國密即國家密碼管理局公布認定的國產密碼算法&#xff0c;也稱為商用密碼&#xff08;在此語境下與國密通用&#xff09;&#xff0c;指能夠實現商用密碼算法的加密、解密和認證等功能的技術&#xff0c;涵蓋密碼算法編程技術和密碼算法芯片、…

打卡35天

模型可視化與推理 知識點回顧&#xff1a; 三種不同的模型可視化方法&#xff1a;推薦torchinfo打印summary權重分布可視化 進度條功能&#xff1a;手動和自動寫法&#xff0c;讓打印結果更加美觀 推理的寫法&#xff1a;評估模式 作業&#xff1a;調整模型定義時的超參數&…

kafka之操作示例

一、常用shell命令 #1、創建topic bin/kafka-topics.sh --create --zookeeper localhost:2181 --replications 1 --topic test#2、查看創建的topic bin/kafka-topics.sh --list --zookeeper localhost:2181#3、生產者發布消息命令 &#xff08;執行完此命令后在控制臺輸入要發…

網絡安全基礎--第七課

路由表 路由器的轉發原理&#xff1a;當一個數據包進入路由器&#xff0c;路由器將基于數據包中的目標IP地址&#xff0c;查詢本地 路由表&#xff0c;若表中存在記錄&#xff0c;則將無條件按記錄轉發&#xff0c;若沒有記錄&#xff0c;路由器不能泛洪&#xff0c;因為路由器…

Java SpringBoot 扣子CozeAI SseEmitter流式對話完整實戰 打字機效果

書接上回&#xff1a;springBoot 整合 扣子cozeAI 智能體 對話https://blog.csdn.net/weixin_44548582/article/details/147457236 上文實現的是一次性等待并得到完整的AI回復內容&#xff0c;但隨著問題和AI的邏輯日趨復雜&#xff0c;會明顯增加這個等待時間&#xff0c;這對…

《AVL樹完全解析:平衡之道與C++實現》

目錄 AVL樹的核心概念數據結構與節點定義插入操作與平衡因子更新旋轉操作&#xff1a;從理論到代碼雙旋場景深度剖析平衡檢測與測試策略性能分析與工程實踐總結 0.前置知識&#xff1a;BS樹 代碼實現部分對和BS樹相似的部分會省略。 1. AVL樹的核心概念 1.1 平衡二叉搜索樹…

跨平臺游戲引擎 Axmol-2.6.0 發布

Axmol 2.6.0 版本是一個以錯誤修復和功能改進為主的次要LTS長期支持版本 &#x1f64f;感謝所有貢獻者及財務贊助者&#xff1a;scorewarrior、peterkharitonov、duong、thienphuoc、bingsoo、asnagni、paulocoutinhox、DelinWorks 相對于2.5.0版本的重要變更&#xff1a; 通…

【Django Serializer】一篇文章詳解 Django 序列化器

第一章 Django 序列化器概述 1.1 序列化器的定義 1.1.1 序列化與反序列化的概念 1. 序列化 想象你有一個裝滿各種物品&#xff08;數據對象&#xff09;的大箱子&#xff08;數據庫&#xff09;&#xff0c;但是你要把這些物品通過一個狹窄的管道&#xff08;網絡&#xff…

關于spring @Bean里調用其他產生bean的方法

背景 常常見到如下代碼 Bean public TestBean testBean() {TestBean t new TestBean();System.out.println("testBean:" t);return t; }Bean public FooBean fooBean() {TestBean t testBean();System.out.println("這里看似是自己new的&#xff0c;但因為…

Level1.7列表

1.7_1列表&#xff08;索引切片&#xff09; #1.列表 students[Bob,Alice,Jim,Mike,Judy] print(students)#2.在列表&#xff08;添加不同數據類型&#xff0c;查看列表是否可以運行&#xff1f;是否為列表類型&#xff1f;&#xff09; students[Bob,Alice,Jim,Mike,Judy,123…

Python爬蟲實戰:研究Cola框架相關技術

一、Cola 框架概述 Cola 是一款基于 Python 的異步爬蟲框架,專為高效抓取和處理大規模數據設計。它結合了 Scrapy 的強大功能和 asyncio 的異步性能優勢,特別適合需要高并發處理的爬蟲任務。 1.1 核心特性 異步 IO 支持:基于 asyncio 實現非阻塞 IO,大幅提高并發性能模塊…

vue2中el-table 實現前端分頁

一些接口不分頁的數據列表&#xff0c;一次性返回大量數據會導致前端渲染卡頓&#xff0c;接口不做分頁的情況下前端可以截取數據來做分頁 以下是一個例子&#xff0c;被截取的列表和全量數據在同一個棧內存空間&#xff0c;所以如果有表格內的表單編輯&#xff0c;新的值也會事…

Python + moviepy:根據圖片或數據高效生成視頻全流程詳解

前言 在數據可視化、自媒體內容生產、學術匯報等領域,我們常常需要將一組圖片或一段變動的數據,自動合成為視頻文件。這樣不僅能提升內容表現力,也極大節省了人工操作時間。Python作為數據處理和自動化領域的王者,其`moviepy`庫為我們提供了靈活高效的視頻生成方案。本文將…