Android 中階開發者技能路線圖:2025 年必備能力與面試準備重點

Published on: | Last updated:

從 Junior 到 Mid-level Android Developer,這條路...嗯,說真的,不是多學幾個 library 就沒事了。我自己是覺得,最大的坎,是思維上的轉變。

以前可能就是... 功能做出來就好。但現在,你要開始想,這 App 怎麼活得久、怎麼長得大,還有,怎麼讓下一個人(或三個月後的自己)看得懂。

先說結論:差的不是技術,是「想多深」

Junior 可能在乎「怎麼寫」,但 Mid-level 更在乎「為什麼這樣寫」。

這不是說技術不重要,而是說,你選用某個技術的「理由」,變得比技術本身更重要。像是架構選擇、效能考量、還有可測試性...這些東西。

腦袋要換的幾件事

我覺得最重要的,是開始用「架構」的視角看專案。不再是 Activity / Fragment 塞爆一堆邏輯。

Clean Architecture 很多人講,但說穿了就是「關注點分離」。讓 UI 的事歸 UI,商業邏輯歸商業邏輯。聽起來很空泛,但當你的 App 開始變複雜,有人跟你說「欸那個按鈕的商業邏輯要整個抽換掉」,你就會感謝當初有分層。

它最大的好處,老實說,就是讓你的程式碼可以「被測試」。當你的 UseCase(或 Interactor)乾乾淨淨,不含任何 Android Framework 的東西,你用純 Kotlin/JVM 就能跑單元測試,速度超快,超級爽。

架構分層的概念,不是規則,是思維模式
架構分層的概念,不是規則,是思維模式

再來就是,對非同步的掌握。以前可能一個 `AsyncTask` 走天下...(洩漏年齡了),現在 Coroutines 基本上是標配了。但重點不是會用 `launch` 而已。

你要能分得清楚,什麼時候該用 `async` 來做併發處理。像是有兩個 API 要同時去要資料,然後再合併結果,這就是一個很典型的場景。


// 這段面試蠻愛考的,重點在 coroutineScope 跟 async/await
suspend fun fetchUserDataAndSettings() {
    coroutineScope {
        val userDataDeferred = async { fetchUser() } // 第一個 API
        val userSettingsDeferred = async { fetchSettings() } // 第二個 API,同時發出去

        val userData = userDataDeferred.await() // 等第一個回來
        val userSettings = userSettingsDeferred.await() // 等第二個回來

        // ...拿到兩個資料後,再做點什麼事
        println("User: $userData, Settings: $userSettings")
    }
}

suspend fun fetchUser(): String {
    delay(1000) // 模擬網路延遲
    return "User Data"
}

suspend fun fetchSettings(): String {
    delay(1200) // 模擬網路延遲
    return "Theme: Dark"
}

這段 code 看起來簡單,但它體現了你懂不懂得「節省時間」。兩個網路請求不必一個等一個,可以同時飛出去,總耗時就取決於比較慢的那個,而不是兩者相加。這對 App 的體驗影響很大。

現代 Android 的狀態管理:Flow 的天下

現在用 Jetpack Compose 開發,基本上你無時無刻不在跟「狀態(State)」打交道。這也是跟以前用 XML 拉畫面很不一樣的地方。

所以 `LiveData`、`StateFlow`、`SharedFlow` 這幾個東西的差別,一定要搞懂。我自己是這樣看的:

LiveData StateFlow SharedFlow
主要用途 以前跟 XML View 綁定的好夥伴。知道 Activity/Fragment 的生命週期。 Compose 時代的 UI 狀態管理首選。基本上就是用它來代表畫面的狀態。 用來處理「事件(Event)」,就是那種發出去一次就沒了的,像是 "Toast 顯示一下" 或 "跳轉到下一頁"。
有沒有初始值 可以沒有。一開始是 null。 必須有。這點很重要,它保證你的 UI 永遠有個初始狀態可以顯示。 可以沒有。就是一個...事件廣播器。
黏不黏人 (Sticky) 黏。新的觀察者一進來,會馬上收到最新的那個值。 超黏。它就是為了保存「最新狀態」而生的。 可以設定。`replay` 參數設為 0,就不黏,事件發過就忘了。適合單次事件。
生命週期感知 內建的。這也是它以前最大的優點。 沒有。要自己搭配 `lifecycleScope.launchWhenStarted` 或在 Compose 裡用 `collectAsStateWithLifecycle()` 來處理。 跟 StateFlow 一樣,本身不管生命週期。
個人碎念 說真的...新專案如果全用 Compose,我幾乎想不起來要用它的理由了。 把它想成畫面的「單一事實來源 (Single Source of Truth)」。畫面長怎樣,看它就對了。 千萬不要用 StateFlow 去處理「顯示 Toast」這種事,不然手機一翻轉,StateFlow 會把最後一個值再發一次,Toast 就又彈出來了...很煩。

所以你看,光是「資料流」,就有這麼多細節可以討論。Mid-level 就是要能根據情境,選出最適合的工具,而不是只會一種。這也連結到 DI(依賴注入)。

同時處理多個資料流,是日常工作的一部分
同時處理多個資料流,是日常工作的一部分

依賴注入 (DI):不只是酷,是為了好維護

Dagger Hilt 現在很方便,幾個 annotation (`@HiltViewModel`, `@Inject`) 弄上去,ViewModel 就能拿到它需要的 Repository。

很多國外文章或小專案可能會推 Koin,因為它設定比較簡單。但在台灣,我看到的...特別是比較有規模的公司,好像還是用 Hilt 的居多。可能是因為 Hilt 在編譯期就做檢查,比較穩,比較不會在執行期才炸掉跟你說有東西找不到。

官方文件(Android Developers 網站)當然是推自家的 Hilt,這點沒話說。用 DI 的核心思想,還是為了「解耦合」跟「可測試性」。當你的 ViewModel 可以輕易地在測試中被建立,並餵給它一個假的 Repository,你就能專心測 ViewModel 的邏輯,這多棒啊。


// 在 ViewModel 注入 Repository
@HiltViewModel
class MyUserViewModel @Inject constructor(
    private val userRepository: UserRepository // 直接從建構子要東西
) : ViewModel() {
    // ... viewmodel 邏輯 ...
}

// 在 Fragment/Activity 裡面拿 ViewModel 就變得很簡單
@AndroidEntryPoint
class UserProfileFragment : Fragment() {
    private val viewModel: MyUserViewModel by viewModels()
    // 搞定。Hilt 會自己想辦法把所有東西生出來。
}

還有一些零碎但重要的事

除了上面那些大觀念,還有一些具體的技術債...不是,是技能要點。

  • 資料庫:Room 要熟。不只是會 CRUD,更重要的是「資料庫升級 MIGRATION」。App 上線後,十之八九會需要改 table 結構,你總不能叫使用者把 App 刪掉重裝吧?這時候 migration 怎麼寫就很關鍵。
  • 效能優化:App 啟動速度。這點超重要。可以用 Baseline Profiles 預先編譯好 Compose 的部分,體感會快一些。還有就是不要在 `Application.onCreate()` 裡面做一堆有的沒的初始化,善用 Lazy a.k.a 懶加載。
  • 測試:單元測試 (Unit Test) 和 UI 測試 (UI Test) 至少要會寫。用 JUnit + Mockito/MockK 測商業邏輯,用 Espresso 或 Compose 的 Testing API 測畫面互動。Mid-level 不只是要會開發,也要能為自己的程式碼品質背書。
冷流與熱流的差別,一個等你來才動,一個一直在流動
冷流與熱流的差別,一個等你來才動,一個一直在流動

說到底,從 Junior 到 Mid,就像是從一個「聽指令的士兵」變成一個「需要看地圖、規劃路線的班長」。

你手上的工具(Kotlin、Compose、Coroutines)可能都一樣,但你開始需要思考戰略層面的問題了。這可能就是最大的差別吧。

那你自己覺得,從 Junior 到 Mid 最難的是學會這些新技術,還是改變思考問題的方式?

Related to this topic:

Comments

  1. Guest 2025-09-17 Reply
    哇靠,這篇文章超級實用!剛好最近在學Android開發,尤其是協程和Clean Architecture那部分超級有感。感覺可以幫我解決不少coding的盲點,期待深入研究一下!
  2. Guest 2025-08-30 Reply
    哇,這篇文章好像很專業耶!我兒子正在學程式,不過我有點擔心,他能不能跟上這麼多技術細節呢?聽起來好像很複雜的樣子,不知道對初學者友善嗎?
  3. Guest 2025-08-10 Reply
    嘿,這份 Android 技術指南真的很扎實!我們團隊正好在尋找這種深入又實務的內容。有空聊聊更多細節嗎?特別想聽聽協程和 Clean Architecture 的經驗分享。
  4. Guest 2025-04-11 Reply
    這篇整理得蠻全面的,不過小弟有點好奇啊~像LiveData和StateFlow這種差異性討論,實務上真的會影響開發節奏嗎?我們團隊用起來感覺差異沒那麼明顯說... 還是說各位有踩過什麼特別的坑可以分享?
撥打專線 LINE免費通話