Daily Digest

每日新聞摘要

2026年11月02日

今日總結

📝 今日焦點 - Todorant 上線、KMP 遷移、Compose 升級與 AgentContext 顯示 Kotlin 生態正從單一 Android 開發走向跨平台與 AI 輔助。 🔧 效能最佳化 - R8、flowOn、Baseline Profiles、fontScale 測試與 Flow 合併語意提醒團隊,效能與正確性常在發佈、UI 與非同步邊界暴露。 🏗 架構設計 - FinLedger、QuickTube 與 MVI 文章強調以交易回復、單向資料流、DI 與組合取代粗暴 CRUD、BaseViewModel 與過度分層。 ✅ 測試與品質 - Mutation testing、PIT、預覽與截圖測試、以及 WebSocket 冪等處理,凸顯測試要覆蓋真實使用情境與失敗模式。 🚀 語言演進 - virtual threads 對照協程、fold/reduce、flatMap 系列與 Flow invariant,再加上 Kotlin 2.4.20 Swift export,顯示語言與平台互通持續推進。

01

How Todorant's native Android app reached Google Play in four days, and lost 4.5 MB on the way

Dev.to Kotlin 作者:borodutch.eth 💎🤲 發布:11-02 10:30

Todorant 的原生 Android App 如何在四天內上架 Google Play,並一路瘦身 4.5 MB

正式上架的版本只有 3.26 MB,因為四個版本修掉了只會在真實發佈環境出現的問題。

重點摘要

以 Kotlin 和 Jetpack Compose 重寫的原生 Android App,在四天內從測試版走到 Google Play 正式版。
Google 登入需重建 Cloud 專案並同時加入上傳金鑰與 Play 簽署金鑰指紋;Google Calendar 同步也被移除。
R8 造成 QR 登入當機,另外移除 Apple 專用的 SF Pro 字型後,APK 少了 4.5 MB。
展開詳細摘要

Todorant 將 Android App 以原生 Kotlin 與 Jetpack Compose 重寫後,在四天內完成 Google Play 上架,但正式發佈過程暴露出測試版看不到的問題。團隊先是因為原本的 Google Cloud 專案被刪除而重做登入設定,並補上上傳金鑰與 Play 簽署金鑰的指紋;接著移除已失效的 Google Calendar 同步,再修正由 R8 引發的 QR 登入當機。之後刪除僅適用於 Apple 平台的 SF Pro 字型,讓 APK 再瘦身 4.5 MB。文中也提到 F-Droid 版本、權限清理,以及上線後修補的實際使用者問題。

02

Dropped on the Floor: Conflation in Kotlin Flows and the UI Events You Never Saw

Dev.to Kotlin 作者:Android Expert 發布:11-02 11:50

掉到地板上:Kotlin Flow 的合併與你從未看見的 UI 事件

模糊界線的機制是 conflation,而它也不是值消失的唯一原因。

重點摘要

StateFlow 預設會合併,只保留最新值,會跳過中間更新。
把事件當成狀態來建模,可能因為相等比較或合併而被吞掉。
UI effect 應選對傳遞原語:Channel、buffered SharedFlow,或帶 ID 的佇列狀態。
展開詳細摘要

這篇文章說明 Kotlin Flow 的 conflation 如何悄悄把 UI 事件變成資料遺失。StateFlow 設計上只保留最新值,適合畫面狀態,卻不適合導頁、顯示收據這類一次性效果。文中指出,以可空欄位表示事件、誤用 SharedFlow 設定、collectLatest,以及具合併語意的 buffer,都可能讓事件消失或在執行中被取消。接著比較幾種修正方式:對於始終有收集者的情境可用 buffered SharedFlow;單一消費者的 UI effect 則適合 Channel;若一定要放進 state,則應以帶識別碼的佇列保存。核心原則是先分清楚值與事件,再選擇對應的傳遞語意。

03

Deleting a Transaction Should Be Surgical — Here's How to Do It Right

Dev.to Kotlin 作者:DEVANSHU PATIL 發布:11-02 13:00

刪除交易必須像手術一樣精準:FinLedger 的正確做法

刪除金融交易不是單純刪掉資料列,而是一個對帳事件。

重點摘要

不能只刪交易列,還要回沖相關帳戶餘額。
借貸與拆帳等關聯資料必須同步更新,避免帳務失真。
附件檔案要一併清理,並在啟動時掃除孤兒檔案。
展開詳細摘要

FinLedger 將刪除交易視為一個協同的對帳流程,而不是單純執行 SQL DELETE。系統會先查出交易與其關聯帳戶、附件,接著在 SQLite 的原子交易中反轉原始記帳分錄,讓餘額回到正確狀態。若交易牽涉借貸或拆帳,也會同步更新伴隨資料,維持關聯一致。資料庫提交後,再刪除本機收據檔案並處理雲端同步標記。由於檔案系統不屬於 SQLite 的 ACID 範圍,應用程式也會在啟動時掃描並清除殘留的孤兒附件。

04

Why Your "Real-Time" Chat App Duplicates Messages on Reconnect (and the Fix)

Dev.to Kotlin 作者:YADNYESH RANA 發布:11-02 14:23

為什麼即時聊天 App 在重新連線後會重複訊息,以及如何修正

WebSocket 的重新連線不是續傳,而是一條全新的連線。

重點摘要

網路中斷後重連,可能導致訊息被重送或重播。
只做追加寫入的客戶端會把同一則訊息存成兩筆。
做法是保存可持久化的最後訊息 ID,並讓資料庫忽略重複寫入。
展開詳細摘要

聊天 App 在網路中斷後出現重複訊息,通常不是 UI 問題,而是重連流程沒有正確處理。WebSocket 重新連線並非續傳,而是全新的連線,因此伺服器可能重播斷線前後的訊息;若重連失敗事件短時間內觸發多次,也可能產生多次成功連線與重複回補。文章建議客戶端從本機資料庫讀取最後收到的 server-assigned ID,透過 resumeFrom 明確告知伺服器已擁有的進度,同時在資料庫層以唯一鍵與 IGNORE 讓重送訊息變成無害的冪等操作。

05

Why Your Flow Refuses to Hop Threads: Context Preservation, flowOn, and channelFlow in Kotlin

Dev.to Kotlin 作者:Android Expert 發布:11-02 14:47

為什麼你的 Flow 不肯切換執行緒:Kotlin 的上下文保留、flowOn 與 channelFlow

flow { } 的限制並不是任意設下的。

重點摘要

emit 必須與 collect 位於同一個 coroutine context
flowOn 會把上游搬到另一個執行緒,並帶來緩衝區
channelFlow 與 callbackFlow 用於並行或回呼式產生者
展開詳細摘要

本文說明為何在普通的 flow { } 內把 emit 放進 withContext、launch 或 async,會觸發「Flow invariant is violated」。Kotlin 強制 emit 必須與 collect 使用相同的 coroutine context,讓下游運算子能維持順序執行、可預測的執行環境與不需加鎖的狀態。作者建議,多數情況應把 dispatcher 切換下放到 suspend 函式中,讓 flow 本身保持簡單;若是長時間的上游工作,可用 flowOn տեղափոխ動整段上游;當多個 coroutine 或不同 context 需要同時產生值時,則應使用 channelFlow。文章也補充 callbackFlow、flowOn 的隱含緩衝、常見錯誤樣式與可固定不變式的測試做法。

06

Release Build Autopsy: Following One Kotlin Line from Gradle to the First Frame

Dev.to Kotlin 作者:Android Expert 發布:11-02 14:52

Release Build Autopsy:追蹤一行 Kotlin 從 Gradle 到第一幀

我們一路追蹤一行 Kotlin,從 ./gradlew assembleRelease 經過 Gradle、AAPT2、R8、簽署、Play 傳遞,最後到裝置上的 ART。

重點摘要

Gradle 的 configuration 階段可能讓每次執行都變慢,並破壞快取命中。
AAPT2、Manifest 合併與資源縮減都可能只在 release 變體出錯。
R8、封裝與 Baseline Profiles 會以不同方式影響 release 行為。
展開詳細摘要

本文沿著 Android 發佈管線追蹤一行 Kotlin 程式,從 Gradle 的初始化與組態、AAPT2 資源處理、Manifest 合併、Kotlin/Java 編譯,到 R8 縮減與混淆、封裝簽署、Play 傳遞,最後抵達裝置上的 ART。作者用多個真實常見的失敗模式說明:configuration-time 工作會拖慢所有 Gradle 呼叫,動態載入的資源可能被 shrinker 刪除,透過反射或字串存取的類別可能被 R8 移除或改名,而舊版裝置若未啟用 library desugaring 也會在執行期出錯。文章也說明 AAB 的語言分割、簽章機制,以及 Baseline Profiles 如何改善首次啟動。

07

The Seed Decides Everything: fold() vs reduce() in Production Kotlin on Android

Dev.to Kotlin 作者:Android Expert 發布:11-02 14:56

種子決定一切:Android 生產環境中的 Kotlin fold() 與 reduce()

真正的差異只在起始累加值,但它會影響型別彈性、空集合行為,以及 lambda 能否安全修改資料。

重點摘要

fold 從明確的種子值開始;reduce 則從第一個元素開始。
空集合會讓 reduce 直接丟例外,而 fold 可安全回傳種子或改用 reduceOrNull。
種子選錯可能導致共用狀態被修改、數值溢位,或讓非交換運算的結果改變。
展開詳細摘要

fold() 和 reduce() 看起來很像,但起始累加值不同,會連帶影響型別規則、空輸入行為與失敗模式。本文說明為何在需要建立不同結果型別、處理可能為空的集合,或重建可重放的狀態時,fold 通常是更合適的選擇;而當第一個元素本身就是合理起點,且所有值形狀相同時,reduce 才較自然。不過 reduce 在空集合上會丟出例外,若在原地修改累加值,還可能意外改到第一個元素。文章也提醒要避免共用可變種子、每步複製造成 O(n²)、以 Int 種子導致整數溢位,以及在未確認種子是否為恆等元前就把 reduce 換成 fold。

08

Inside Android Layoutlib: How View and Compose Previews Reach the Canvas

ProAndroidDev 作者:Ravi Rawal 發布:11-02 14:47

深入 Android Layoutlib:View 與 Compose 預覽如何到達 Canvas

Layoutlib 會把不同的 UI 模型接到主機端的渲染環境中。

重點摘要

Layoutlib 可在不啟動裝置執行階段的情況下渲染預覽。
View 與 Compose 走不同渲染路徑,但共用主機端基礎架構。
預覽成功不代表在真機上的行為一定一致。
展開詳細摘要

本文說明 Android Studio 預覽在 Layoutlib 之下如何運作,從 XML inflate 或編譯後的 composable,一路經過量測、版面配置、繪製到最終影像。文中區分了以 View 為主的路徑:建立 Android View 階層;以及 Compose 路徑:在 View 型主機中執行 Compose,但由 Compose 自行維護內部 UI 樹。作者也解釋為何 Layoutlib 需要 framework delegate、預覽失敗可能發生在依賴或執行階段邊界,以及為何預覽只能作為參考,不能取代在模擬器或真機上的測試。

09

Migrating a Real Android App to Kotlin Multiplatform 2/4 — What Moved for Free, and What Hurt

ProAndroidDev 作者:Daniel Voko 發布:11-02 14:51

將一個真實 Android App 遷移到 Kotlin Multiplatform 2/4:哪些幾乎零成本,哪些最棘手

真正影響進度的,不是函式庫是否支援 KMP,而是你的程式碼和平台 API 綁得有多緊。

重點摘要

Koin、Ktor、SQLDelight 大致可順利移到 commonMain。
應用程式本身對平台 API 的耦合,遠比函式庫的 KMP 支援更關鍵。
java.time、檔案處理與本機儲存是最難處理的遷移痛點。
展開詳細摘要

這一篇延續遷移實錄,說明哪些部分幾乎不用改就能進入 Kotlin Multiplatform,哪些部分則最耗時。作者指出,Koin、Ktor 與 SQLDelight 因為原本架構就偏向共享程式碼,所以遷移相對順利;真正拉長工期的是程式碼本身對 Android 與其他平台 API 的耦合。文中也比較了 expect/actual 與 DI 的取捨,說明日期處理、檔案上傳與本機儲存為何特別容易踩雷。核心結論是:先盤點平台耦合、讓 DI 承擔平台差異,並在一開始就加入第二個目標平台到 CI。

10

Pineapple on Pizza: A Developer’s Guide to the Native vs. Cross-Platform Debate

Medium Kotlin 作者:Geekhaven Technical Society 發布:11-02 07:50

鳳梨披薩:原生與跨平台之爭的開發者指南

沒有人特別要求鳳梨披薩,就像這些框架之間的比較一樣。

重點摘要

以鳳梨披薩比喻框架之間的比較。
將原生與跨平台之爭描述為帶有爭議性的議題。
目前提供的內文未包含更多技術細節。
展開詳細摘要

這段文字用帶有戲謔意味的比喻,將框架比較類比為「鳳梨披薩」這種具爭議性的話題,暗示原生與跨平台之爭並非人人都真正想要的討論。摘錄內容沒有進一步提供技術論點、平台細節或結論,因此只能確認作者是在以幽默方式引出這場辯論,而非提出具體主張。

11

Domain Layer Gerçekten Şart mı? 3 Satırlık UseCase’lerin Peşinde

Medium Kotlin 作者:Bahadireray 發布:11-02 11:31

真的需要 Domain Layer 嗎?追尋三行程式的 UseCase

在每個 repository 函式前面都加上 UseCase,不一定是架構;有時候只是多了更多資料夾。

重點摘要

質疑每個 repository 呼叫都需要一層 UseCase 包裝
指出額外層次可能只是增加資料夾與間接性
進一步追問是否可以由 ViewModel 直接呼叫
展開詳細摘要

本文質疑在 Kotlin 應用中,Domain Layer 是否真的每次都不可或缺。作者認為,替每個 repository 函式前都加上一個 UseCase,不必然代表更好的架構;有時只是多了層次與更多資料夾而已。文章接著提出更簡化的做法,追問是否可以讓 ViewModel 直接呼叫資料層,而不必經過那些只有三行程式的 UseCase。整體重點在反思過度分層,而非否定 Domain 分層本身的價值。

12

Understanding MVVM in Android with Kotlin: A Beginner-Friendly Guide

Medium Kotlin 作者:Salunkhesonali 發布:11-02 12:58

使用 Kotlin 理解 Android 中的 MVVM:初學者友善指南

了解 Model、View 與 ViewModel 如何協同運作,打造乾淨且易於維護的 Android 應用程式。

重點摘要

介紹 Android 中的 MVVM 模式
說明 Model、View、ViewModel 的分工
聚焦於乾淨、可維護的應用程式架構
展開詳細摘要

本文以初學者易懂的方式介紹 Android 開發中的 MVVM 與 Kotlin。內容說明 Model、View 和 ViewModel 如何彼此協作,並將這種架構視為打造更乾淨、較易維護的 Android 應用程式的方法。文章定位為入門指南,幫助讀者理解各元件的基本角色,以及它們在 Android 應用架構中的位置。

13

Daily Kotlin: KMP Architecture & Project Structure (commonMain vs Platform Source Sets)

Medium Kotlin 作者:Jason Kwon 發布:11-02 13:03

Daily Kotlin:KMP 架構與專案結構(commonMain 與平台 Source Sets)

掌握多平台 source sets、編譯目標、階層模板與依賴共享

重點摘要

介紹 KMP 的架構與專案結構
重點說明 commonMain 與平台 source sets 的差異
涵蓋 source sets、編譯目標與依賴共享
展開詳細摘要

本文聚焦於 Kotlin Multiplatform 專案的架構與結構,特別是 commonMain 與各平台 source sets 的關係。內容提到多平台開發中的幾個核心概念,包括 source sets、編譯目標、階層模板,以及依賴共享。整體主旨是協助讀者理解共用程式碼與平台專屬程式碼在 KMP 中如何分層與組織。

14

Kotlin 2.4.20 Swift Export Improves iOS Interop

Medium Kotlin 作者:AndroidLab by Andre 發布:11-02 13:44

Kotlin 2.4.20 的 Swift Export 改善 iOS 互通性

對於跨平台分享程式碼的 Android 開發者來說,這是一篇值得一讀的文章。

重點摘要

重點在 Kotlin 2.4.20 的 Swift export 改善。
主題是提升與 iOS 的互通性。
面向會共享程式碼的 Android 開發者。
展開詳細摘要

這篇文章提到 Kotlin 2.4.20 的 Swift export 改進,主題聚焦於提升與 iOS 的互通性,對有跨平台共用程式碼需求的 Android 開發者尤其相關。不過,原文提供的內容非常簡短,沒有說明具體技術細節、實作方式或效能數據,因此可確定的重點只有這次版本更新與 iOS 互通性的關聯。

15

Jetpack Compose 1.13 fixes what annoyed me!

Medium Kotlin 作者:AndroidLab by Andre 發布:11-02 13:59

Jetpack Compose 1.13 修正了讓我困擾的問題

我正準備把我的 side project 升級到最新版本的 Compose,原本以為會出現很多錯誤;結果什麼都沒壞。

重點摘要

升級到最新的 Compose 版本沒有造成重大破壞。
作者原本預期會出現很多錯誤,但實際上沒有。
這篇文章主要是在分享升級過程的感受。
展開詳細摘要

作者表示,他在準備把自己的 side project 升級到最新版本的 Compose 時,原本預期會遇到很多錯誤,但實際上沒有任何東西壞掉。這篇內容只是 Medium 上的一則簡短心得,重點在於升級過程出乎意料地順利,帶來鬆了一口氣的感受;提供的內文並沒有列出具體修正項目、API 變動或相容性問題。

16

Gradle Isolated Projects: What Breaks, and What Replaces It

Medium Kotlin 作者:Ramadan Sayed 發布:11-02 14:01

Gradle Isolated Projects:哪些會失效,以及可由什麼取代

每個大型 Gradle 建置都有相同的兩個習慣:根目錄的 allprojects 區塊,以及至少一個模組會跨界存取其他模組。

重點摘要

大型 Gradle 建置常依賴根目錄的 allprojects 區塊。
模組之間經常跨越邊界直接存取彼此。
文章聚焦 Isolated Projects 會讓哪些做法失效,以及可用什麼取代。
展開詳細摘要

文章指出,大型 Gradle 建置常見兩種做法:在根目錄使用 allprojects 區塊,以及讓某個模組直接跨模組存取其他模組。作者以 Gradle Isolated Projects 為主題,討論這些習慣會在哪些地方出問題,以及可能的替代方向。由於目前提供的內容只有文章開頭,無法推斷更細的實作細節或結果。

17

Android 18–5 features I want to see in a future Android version!

Medium Kotlin 作者:AndroidLab by Andre 發布:11-02 14:06

我想在未來 Android 版本中看到的 18–5 項功能!

幾年前,我還會告訴自己,別對下一個 Android 版本太過期待。

重點摘要

作者表示,過去他會刻意避免對新的 Android 版本過度興奮。
這篇文章主題是他希望未來 Android 版本加入的功能。
預覽版開始釋出後,原文仍需前往 Medium 繼續閱讀。
展開詳細摘要

這篇文章以作者對 Android 新版本的個人期待作為開場。作者提到,幾年前自己還會提醒自己不要對另一個 Android 版本太興奮,但當 preview 開始陸續推出時,這種心情又被喚起。截取內容尚未列出具體功能,只顯示作者將在後文談論他希望未來 Android 版本具備的特性,完整內容則要到 Medium 繼續閱讀。

18

Jetpack Compose 1.12 Has Released, And 1.13 Is Already In Motion!

Medium Kotlin 作者:Sixtin - Mobile App Developer 發布:11-02 14:44

Jetpack Compose 1.12 已發布,1.13 也已經啟動開發

有哪些新內容、Beta 版會帶來什麼,以及升級前該先確認什麼

重點摘要

Jetpack Compose 1.12 已經發布。
1.13 已進入 beta 推進階段。
文章提醒升級前先檢查相關項目。
展開詳細摘要

Jetpack Compose 1.12 已正式發布,而 1.13 也已開始推進。文章聚焦三個面向:這次版本帶來哪些新內容、下一版 Beta 階段會出現什麼,以及升級前應先確認哪些事項。雖然摘錄內容沒有列出完整技術細節,但主旨很明確:從穩定版過渡到下一個版本時,開發者應先留意相容性與升級檢查,避免直接套用造成問題。

19

Migrating a Real Android App to Kotlin Multiplatform 2/4 — What Moved for Free, and What Hurt

Medium Kotlin 作者:Daniel Voko 發布:11-02 14:51

將一個真實 Android App 遷移到 Kotlin Multiplatform 2/4——哪些內容幾乎無痛搬移,哪些地方帶來阻礙

第 2 部分:哪些內容幾乎可直接搬移,哪些地方造成困擾

重點摘要

本文是將真實 Android App 遷移到 Kotlin Multiplatform 的第二 भाग。
重點在於哪些內容幾乎不用額外處理就能搬過去,以及哪些部分帶來痛點。
這是作者在 ProAndroidDev 上的實作經驗系列之一。
展開詳細摘要

這是關於將一個真實 Android App 遷移到 Kotlin Multiplatform 的系列第二篇。文章聚焦在遷移過程中的兩個面向:哪些內容幾乎可以直接搬移,以及哪些地方在實作上帶來阻礙與困擾。從現有文字可知,這篇文章是作者延續前文的實務分享,屬於系列中的第 2 部分,而非通用教學或對遷移成果的全面結論。內容刊登於 ProAndroidDev,主題明確指向真實專案的遷移經驗。

20

Java Virtual Threads vs Kotlin Coroutines: Suspension Models and the Shifting Bottleneck

Dev.to Kotlin 作者:Yongho Hwang 發布:11-02 00:51

Java 虛擬執行緒與 Kotlin 協程:暫停模型與瓶頸轉移

兩種作法都只是降低等待成本,並不會增加可用資源總量。

重點摘要

虛擬執行緒把暫停隱藏在程式碼之外,協程則以 suspend 明確標示。
瓶頸會從執行緒數量轉移到資料庫連線、外部 API 或磁碟等下游資源。
ThreadLocal、pinning、阻塞 I/O 的影響會在執行階段顯現,而不是只在程式碼中出現。
展開詳細摘要

本文從暫停機制比較 Java virtual threads 與 Kotlin coroutines。虛擬執行緒屬於 stackful,由執行階段保存並恢復整個堆疊,因此暫停點在程式碼中幾乎不可見;協程則是 stackless,由編譯器改寫 suspend 函式,透過 Continuation 返回並重新呼叫,讓暫停點明確暴露。作者指出,兩者都只是降低等待成本,並不增加總資源,因此當執行緒限制消失後,瓶頸會轉移到資料庫連線池、外部 API 額度或磁碟。文章也分析 ThreadLocal、pinning、阻塞 I/O、JFR 監控與版本選擇,強調選型應看工作負載的真正等待資源。

21

Your Compose Screenshot Tests Never Run at fontScale 1.3 — and That's Where Your Layout Breaks

Dev.to Kotlin 作者:YADNYESH RANA 發布:11-02 03:47

你的 Compose 截圖測試從未在 fontScale 1.3 下執行——而版面就在那裡崩壞

多數 Compose 截圖設定都只用固定裝置設定渲染,從未覆蓋使用者真正會用到的 fontScale。

重點摘要

大多數截圖測試只在 fontScale 1.0 執行,忽略無障礙字體縮放。
固定寬度的價格欄位在 fontScale 1.3 下可能被截斷,且不會報錯。
可透過調整 deviceConfig 或 LocalDensity,為高風險版面加入大字體變體。
展開詳細摘要

這篇文章指出,許多 Compose 截圖測試套件只在預設的 fontScale 1.0 下渲染,因此無法覆蓋使用者實際會開啟的無障礙字體縮放。當可伸縮文字旁邊放著固定寬度的元素,例如價格欄位,版面在 1.3 倍字體下就可能悄悄壓縮或截斷。作者以 $1,249.00 為例說明,TextOverflow.Ellipsis 會讓價格在沒有當機、沒有 lint 警告、測試全綠的情況下變成錯誤顯示。解法不是換新工具,而是為 Paparazzi 的 DeviceConfig 或 Compose 測試中的 LocalDensity 加入 fontScale 1.3f 的渲染版本。

22

Building an Android AI Agent, Part 12: AgentContext — Knowing What the User Is Doing Before They Ask

Dev.to Kotlin 作者:StareBrain 發布:11-02 03:58

打造 Android AI Agent,第 12 部:AgentContext——在使用者開口前先理解他正在做什麼

Agent 應該先有一個可運作的上下文模型:目前哪個 App 正在前景、使用者在中斷前做了什麼,以及接下來可能要做什麼。

重點摘要

AgentContext 會記錄目前與前一個 App、近期切換、待處理任務與信心等級。
App 切換模式可在使用者表達前推測其意圖。
依信心等級決定自動帶入、提出建議或直接詢問。
展開詳細摘要

本篇介紹 AgentContext:一個只存在於目前工作階段、用來預測使用者意圖的上下文模型。它會保存目前與前一個套件名稱、近期 App 切換、當前畫面截圖、待處理任務、最後一次使用者意圖與信心等級。建構器會根據最近 60 秒內的切換次數推斷信心:切換頻繁代表 HIGH,訊號有限為 MEDIUM,沒有近期活動則是 LOW。這些資訊會被整理成精簡提示詞送進 LLM,且只保留最近幾次切換與當前畫面,以避免雜訊。系統再依信心等級決定初始互動方式:HIGH 直接帶入上下文,MEDIUM 先建議再確認,LOW 才會主動提問;此外,超過五分鐘的上下文會被視為過期。

23

Why Editing a Transaction In-Place Is the Fastest Way to Corrupt Your Ledger

Dev.to Kotlin 作者:DEVANSHU PATIL 發布:11-02 04:30

為什麼直接原地編輯交易是最快破壞分類帳的方法

FinLedger 不直接更新 SQL 欄位,而是先反轉原始過帳,再以原子方式套用修改後的交易。

重點摘要

原地修改交易可能讓帳戶餘額與現實狀況失去一致。
FinLedger 採用兩階段對帳:先撤銷原始過帳,再套用新的過帳。
Room 的 withTransaction 可讓整個編輯要嘛完整提交,要嘛安全回滾。
展開詳細摘要

本文說明,個人理財應用不能把交易編輯當成一般 CRUD 更新。若直接在資料庫中原地修改交易,原先已影響餘額與報表的經濟事件不會自動重算,容易造成帳本失衡。FinLedger 的做法是先還原原交易的過帳,再驗證並套用新交易,並把整個流程包在 Room 的 withTransaction 與 SQLite 交易中,以確保原子性。如此一來,不論是金額、帳戶、交易類型,甚至跨越帳單邊界的日期變更,都能維持分類帳的數學一致性。

24

I built QuickTube, an open-source Android video & music downloader in Jetpack Compose

Dev.to Kotlin 作者:Asadullah Hil Galib 發布:11-02 06:39

我用 Jetpack Compose 打造了 QuickTube:一款開源的 Android 影音下載器

QuickTube 讓你不用廣告或帳號,就能搜尋、觀看並儲存影片與音樂。

重點摘要

可搜尋與觀看 YouTube,支援即時建議、熱門動態、音樂動態、留言與內嵌播放器。
可從 YouTube 與 1,800+ 其他網站下載,支援 144p 到 4K,也可僅下載音訊。
支援分享即下載、內建瀏覽器偵測影片、批次下載播放清單與頻道,並可背景播放。
展開詳細摘要

QuickTube 是一款以 Jetpack Compose 開發的開源 Android App,主打在沒有廣告或帳號的情況下搜尋、觀看並儲存影片與音樂。它支援 YouTube 的搜尋與播放、即時建議、熱門與音樂動態、留言,以及內嵌播放器;也能從 YouTube 和 1,800 多個網站下載,提供多種畫質或僅音訊下載。App 另外整合分享即可下載、內建瀏覽器自動辨識頁面中的影片、批次處理播放清單與頻道,並支援背景播放、下載庫與主題。作者也提到其技術重點包含裝置端合併串流、HLS 轉 MP4,以及從 WebView 讀取播放器資料。

25

Android MVI Architecture with MVIStateStore: A Complete Guide

Dev.to Kotlin 作者:StudyInPark 發布:11-02 06:59

使用 MVIStateStore 的 Android MVI 架構:完整指南

本指南說明如何以 Jetpack Compose、Kotlin Coroutines/Flow 與集中式 MviStateStore 建立 MVI 架構。

重點摘要

以單向資料流建立可預測的狀態管線
用單一不可變 UiState 作為單一真實來源
以純 reducer 與 Coroutine Channels 處理狀態與一次性副作用
展開詳細摘要

這篇指南說明如何在 Android 中結合 Jetpack Compose、Kotlin Coroutines/Flow 與集中式 MviStateStore 建立 MVI 架構。內容重點包括單向資料流、以單一不可變 UiState 管理畫面全部狀態,以及透過純 reducer 函式實作同步且具執行緒安全的狀態轉換。文中也介紹如何用 Coroutine Channels 處理導覽、Toast 與 Snackbar 等一次性副作用,避免螢幕旋轉後重複觸發,並以完整 Kotlin 範例比較 MVI 與 MVVM。

26

Day 10 of 12-Day Android Interview Preparation Plan

Medium Kotlin 作者:Ishant 發布:11-02 00:13

12 天 Android 面試準備計畫第 10 天

效能最佳化與 Android 內部機制

重點摘要

聚焦 Android 效能調校
涵蓋 Android 內部機制
屬於 12 天面試準備計畫的一部分
展開詳細摘要

這篇文章是 12 天 Android 面試準備計畫的第 10 天,主題聚焦在效能最佳化與 Android 內部機制。由於內文極為簡短,內容主要只點出本篇的主題,沒有展開細節或實作說明。整體上,它是該系列面試準備內容中的一篇,並引導讀者前往 Medium 閱讀完整文章。

27

Race, Queue, or Cancel: Choosing the Right flatMap for Your Kotlin Flow

Medium Kotlin 作者:Android Expert 發布:11-02 05:07

競速、排隊還是取消:為你的 Kotlin Flow 選對 flatMap

同一個輸入下,flatMapMerge、flatMapConcat 與 flatMapLatest 的差異,以及它們各自隱藏的生產環境失敗模式。

重點摘要

比較 flatMapMerge、flatMapConcat、flatMapLatest 在相同輸入下的行為差異。
聚焦於 Kotlin Flow 實務上真正重要的語義差別。
指出每種 operator 可能遮蔽的生產環境失敗模式。
展開詳細摘要

這篇文章說明在 Kotlin Flow 中,flatMapMerge、flatMapConcat 與 flatMapLatest 套用到相同輸入時,行為會如何不同。作者不是把它們視為可互換,而是從競速、排隊與取消上游工作三種角度來看待選擇。文章也提醒,這些 operator 各自可能掩蓋不同的生產環境失敗模式,因此在實際使用前理解其語義非常重要。

28

Your Tests Are Green. Are They Actually Catching Bugs?

Medium Kotlin 作者:Rahul Dhanuka 發布:11-02 06:40

你的測試是綠燈,但真的有抓到 Bug 嗎?

這是一份使用 PIT 在 Kotlin 中進行 mutation testing 的實用指南,從第一次執行到 CI,並包含真實情境與面試題目。

重點摘要

介紹在 Kotlin 中使用 PIT 進行 mutation testing
涵蓋從首次執行到 CI 的流程
包含真實情境與面試題目
展開詳細摘要

本文提供一份以 PIT 在 Kotlin 中實作 mutation testing 的實用指南,切入點是工程師常見的疑問:測試全綠,不代表真的能抓到缺陷。文章說明內容會從第一次執行一路帶到 CI 整合,並搭配一個真實案例與面試題目。依據目前提供的文字,這篇文章重點在於介紹方法與使用情境,沒有額外宣稱成效、效能或已驗證的比較結果。

29

Composition Over Inheritance in Android ViewModels: Stop Writing BaseViewModel

Medium Kotlin 作者:Aslam Hossin 發布:11-02 07:01

Android ViewModel 中的組合優於繼承:別再撰寫 BaseViewModel

如何用 Kotlin 介面委派與 Lifecycle 2.11 的 scope,取代臃腫的 500 行基底類別。

重點摘要

以組合優於繼承來設計 Android ViewModel。
使用 Kotlin 介面委派與 Lifecycle 2.11 的 scope。
避免建立臃腫、長達 500 行的 BaseViewModel。
展開詳細摘要

本文主張 Android ViewModel 應採用組合優於繼承,而不是依賴龐大的共用基底類別。作者指出,可透過 Kotlin 介面委派與 Lifecycle 2.11 的 scope 來取代臃腫的 BaseViewModel 設計,降低對大型共享父類別的依賴。重點在於不要再用動輒 500 行的 base class,而是以更小、更聚焦的元件來組織 ViewModel。