📝 Today’s highlight
- Todorant, KMP migration, Compose upgrades, and AgentContext show Kotlin moving beyond single-app Android work toward multiplatform and AI-assisted workflows.
🔧 Performance tuning
- R8, flowOn, Baseline Profiles, fontScale test coverage, and Flow conflation all show that performance and correctness often surface at release and UI boundaries.
🏗 Architecture design
- FinLedger, QuickTube, and MVI guidance favor transaction rollback, unidirectional flow, DI, and composition over blunt CRUD, BaseViewModel, and extra layers.
✅ Testing and quality
- Mutation testing with PIT, previews, screenshot coverage, and idempotent WebSocket handling stress real-world scenarios and failure modes.
🚀 Language evolution
- Virtual threads vs coroutines, fold/reduce, flatMap operators, Flow invariants, and Kotlin 2.4.20 Swift export show continued language and platform progress.
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
How Todorant's native Android app reached Google Play in four days, and lost 4.5 MB on the way
The version that shipped to Google Play was 3.26 MB instead of 7.74 MB after four releases fixed issues that only appeared in real production builds.
重點摘要
A native Kotlin and Jetpack Compose Android app replaced the old React Native build and reached Google Play in four days.
Google sign-in needed a new Cloud project and both upload-key and Play-signing-key fingerprints; Google Calendar sync was removed.
R8 broke QR-code sign-in, and removing Apple-only SF Pro fonts cut 4.5 MB from the APK.
展開詳細摘要
Todorant’s Android app was rebuilt in native Kotlin and Jetpack Compose and reached Google Play in four days, but the path to release exposed issues that test builds missed. The team fixed Google sign-in by replacing a deleted Google Cloud project and adding both upload and Play signing fingerprints, removed broken Google Calendar sync, and patched an R8-related QR login crash found by Play’s pre-launch report. A later release removed Apple-only SF Pro fonts, shrinking the APK by 4.5 MB. The post also notes a separate F-Droid flavor, permission cleanup, and several fixes for real users after launch.
Todorant 的原生 Android App 如何在四天内上架 Google Play,并瘦身 4.5 MB
最终发布到 Google Play 的版本只有 3.26 MB,因为四次发布修复了只会在真实发布环境里暴露的问题。
重點摘要
这款以 Kotlin 和 Jetpack Compose 重写的原生 Android App,在四天内从测试版走到 Google Play 正式版。
Google 登录需要重建 Cloud 项目,并同时配置上传密钥和 Play 签名密钥指纹;Google Calendar 同步也被移除。
R8 导致二维码登录崩溃,移除仅适用于 Apple 平台的 SF Pro 字体后,APK 少了 4.5 MB。
展開詳細摘要
Todorant 将 Android App 重写为原生 Kotlin 和 Jetpack Compose 后,在四天内完成了 Google Play 上架,但正式发布过程暴露出测试版不会出现的问题。团队先是因为原来的 Google Cloud 项目被删除而重建登录配置,并补上上传密钥和 Play 签名密钥的指纹;随后移除已失效的 Google Calendar 同步,再修复由 R8 引发的二维码登录崩溃。之后删除仅适用于 Apple 平台的 SF Pro 字体,使 APK 再减少 4.5 MB。文章还提到 F-Droid 版本、权限精简,以及上线后针对真实用户的后续修复。
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 版本、權限清理,以及上線後修補的實際使用者問題。
Dropped on the Floor: Conflation in Kotlin Flows and the UI Events You Never Saw
Dev.to Kotlin作者:Android Expert發布:11-02 11:50
Dropped on the Floor: Conflation in Kotlin Flows and the UI Events You Never Saw
The mechanism that blurs the line is conflation, and it is not the only way values vanish.
重點摘要
StateFlow conflates by design; it keeps the latest value and can skip intermediate updates.
Events modeled as state can be lost, duplicated, or swallowed by equality checks and conflation.
For UI effects, prefer the right delivery primitive: Channel, buffered SharedFlow, or queued state with IDs.
展開詳細摘要
This article explains how Kotlin Flow conflation can quietly turn UI events into data loss bugs. StateFlow is designed to keep only the latest value, which is ideal for screen state but wrong for one-off effects like navigation or showing a receipt. The post shows how nullable state fields, misused SharedFlow settings, collectLatest, and conflated buffers can drop events or cancel handlers unexpectedly. It then compares fixes: a buffered SharedFlow for always-present collectors, a Channel for single-consumer UI effects, or explicit queued state with IDs when effects must live in state. The key rule is to distinguish values from occurrences and choose delivery semantics accordingly.
掉到地板上:Kotlin Flow 的合并与那些你从未看到的 UI 事件
模糊边界的机制是 conflation,而它也不是值消失的唯一原因。
重點摘要
StateFlow 默认会合并,只保留最新值,会跳过中间更新。
把事件建模成状态,可能因为相等比较或合并而被吞掉。
UI effect 应选择正确的传递原语:Channel、buffered SharedFlow,或带 ID 的队列状态。
Deleting a Transaction Should Be Surgical — Here's How to Do It Right
Dev.to Kotlin作者:DEVANSHU PATIL發布:11-02 13:00
Deleting a Transaction Must Be Surgical: How FinLedger Does It Right
Deleting a financial transaction is a reconciliation event, not a simple database row drop.
重點摘要
Deletion must reverse postings across related accounts, not just remove a row.
Linked loan and split-expense records must be synchronized to keep balances truthful.
Attachment files must be cleaned up on disk, with startup sweeps for orphaned files.
展開詳細摘要
FinLedger treats transaction deletion as a coordinated reconciliation workflow rather than a simple SQL DELETE. Before removing a record, it inspects linked accounts and attachments, then reverses the original postings inside an atomic SQLite transaction so balances remain correct. If the transaction is tied to lending or split-expense features, companion records are updated to preserve relational truth. After the database commit, local receipt files are deleted and any cloud-sync queue is updated. Because filesystem cleanup is outside SQLite’s ACID boundary, the app also runs a startup sweep to remove orphaned attachment files left behind by unexpected crashes.
Why Your "Real-Time" Chat App Duplicates Messages on Reconnect (and the Fix)
Dev.to Kotlin作者:YADNYESH RANA發布:11-02 14:23
Why Real-Time Chat Apps Duplicate Messages on Reconnect — and How to Fix It
A WebSocket reconnect is not a resume — it's a brand new connection.
重點摘要
Reconnects can replay or redeliver messages after a dropped connection.
A naive client append-only insert path creates duplicate rows.
Fix it with a durable last-message ID and idempotent inserts.
展開詳細摘要
A chat app can duplicate messages after a network drop because a WebSocket reconnect is not a true resume: it is a fresh connection with no shared state. If the server replays messages around the disconnect window, or if multiple reconnect attempts succeed, the same message may be delivered more than once. The article shows that the client should resume from a durable server-assigned message ID stored in local persistence, not in memory, and that the database should ignore duplicate inserts using an idempotent key such as serverId. The core lesson is that reliable chat design needs both resume semantics and duplicate-tolerant storage.
Why Your Flow Refuses to Hop Threads: Context Preservation, flowOn, and channelFlow in Kotlin
Dev.to Kotlin作者:Android Expert發布:11-02 14:47
Why Your Flow Refuses to Hop Threads: Context Preservation, flowOn, and channelFlow in Kotlin
The restriction on flow { } is not an arbitrary limitation.
重點摘要
emit must stay in the collector’s coroutine context
flowOn shifts upstream work and adds a channel buffer
channelFlow and callbackFlow are for concurrent or callback-based producers
展開詳細摘要
This article explains why emitting from inside withContext, launch, or async within a plain flow { } triggers “Flow invariant is violated.” Kotlin enforces that emit runs in the same coroutine context as collect so downstream operators can remain sequential, context-predictable, and unsynchronized. The preferred fix is to move dispatcher switching into suspend functions and keep the flow builder simple. For long-running upstream work, flowOn shifts the producer side, while channelFlow is the right tool when multiple coroutines or contexts must produce values concurrently. The post also covers callbackFlow for listener APIs, the hidden buffering behavior introduced by flowOn, common failure modes, and a test strategy to lock the invariant in place.
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: Tracing One Kotlin Line from Gradle to the First Frame
We follow a single Kotlin line from ./gradlew assembleRelease through Gradle, AAPT2, R8, signing, Play delivery, and finally ART on the device.
重點摘要
Gradle work at configuration time can slow every invocation and break cache hits.
AAPT2, manifest merging, and resource shrinking can fail only in release variants.
R8, packaging, and Baseline Profiles each change release behavior in different ways.
展開詳細摘要
This article traces one Kotlin line through the entire Android release pipeline, from Gradle configuration and task execution to AAPT2, manifest merging, compilation, shrinking, packaging, signing, Play delivery, and ART at runtime. It explains common failure modes such as configuration-time work that slows every build, resource shrinking that removes dynamically referenced assets, R8 stripping or renaming classes reached by reflection, and missing library desugaring on older devices. It also covers distribution details like AAB language splits and signing schemes, then shows how Baseline Profiles help ART compile startup-critical code before first launch. The main point is that release problems usually come from a specific link in the chain, not from magic.
The Seed Decides Everything: fold() vs reduce() in Production Kotlin on Android
Dev.to Kotlin作者:Android Expert發布:11-02 14:56
The Seed Decides Everything: fold() vs reduce() in Production Kotlin on Android
The only real difference is the starting accumulator, but it drives everything else: type flexibility, empty-input behavior, and what your lambda is allowed to mutate.
重點摘要
fold starts from an explicit seed; reduce starts from the first element.
Empty collections make reduce throw, while fold can safely return its seed or reduceOrNull can return null.
Choosing the wrong seed can mutate shared state, overflow numeric totals, or change non-commutative results.
展開詳細摘要
fold() and reduce() may look similar, but the starting accumulator changes their type rules, empty-input behavior, and failure modes. The article shows why fold is the better choice when you need to build a different result type, handle possibly empty collections, or define a replayable state transition. reduce is appropriate when the first element is a valid start and all values share the same shape, but it can throw on empty inputs and can accidentally mutate the first element if the accumulator is modified in place. The post also warns about shared mutable seeds, quadratic copying, integer overflow from using 0 as an Int seed, and semantic changes when swapping reduce for fold without checking whether the seed is a true identity.
Inside Android Layoutlib: How View and Compose Previews Reach the Canvas
ProAndroidDev作者:Ravi Rawal發布:11-02 14:47
Inside Android Layoutlib: How View and Compose Previews Reach the Canvas
Layoutlib connects these different UI models to a host-side rendering environment.
重點摘要
Layoutlib renders previews without launching a device runtime.
Views and Compose follow different rendering paths but share host-side infrastructure.
A successful preview does not guarantee identical behavior on a real device.
展開詳細摘要
This article explains how Android Studio previews work under Layoutlib, tracing the rendering pipeline from XML inflation or compiled composables through measurement, layout, drawing, and final image output. It distinguishes the View-based path, which builds an Android View hierarchy, from the Compose path, where Compose runs inside a View host while keeping its own internal UI tree. The piece also shows why Layoutlib relies on framework delegates, why previews can fail for dependency or runtime reasons, and why a rendered preview is useful but not a substitute for testing on a real device or emulator.
Migrating a Real Android App to Kotlin Multiplatform 2/4 — What Moved for Free, and What Hurt
ProAndroidDev作者:Daniel Voko發布:11-02 14:51
Migrating a Real Android App to Kotlin Multiplatform 2/4: What Moved Easily and What Hurt
The pattern turned out to be simple, and in hindsight obvious: multiplatform support in your libraries matters far less than how tightly your own code is coupled to platform APIs.
重點摘要
Koin, Ktor, and SQLDelight mostly moved cleanly into commonMain.
Platform coupling in app code mattered far more than library KMP support.
java.time, file handling, and local storage were the hardest migration pain points.
展開詳細摘要
This installment of the migration series explains what moved into Kotlin Multiplatform with little effort and what became painful. Koin, Ktor, and SQLDelight largely shifted cleanly because the original architecture already favored shared code, but the real difficulty came from the app’s own coupling to Android and other platform APIs. The author highlights how dependency injection reduced the need for expect/actual, why dates based on java.time were especially disruptive, and why file handling and local storage required different implementations across Android, web, and iOS. The main lesson is to audit platform coupling early, keep DI responsible for platform differences, and build a second target in CI from the beginning.
Pineapple on Pizza: A Developer’s Guide to the Native vs. Cross-Platform Debate
Medium Kotlin作者:Geekhaven Technical Society發布:11-02 07:50
Pineapple on Pizza: A Developer’s Guide to the Native vs. Cross-Platform Debate
Nobody asked for pineapple on pizza, just like the comparison between these frameworks.
重點摘要
The article frames a framework comparison as a polarizing analogy.
It positions the debate as one people did not necessarily ask for.
The provided text does not include further technical details.
展開詳細摘要
The provided text uses a tongue-in-cheek analogy to frame a comparison between frameworks, likening it to the controversial topic of pineapple on pizza. It suggests that, much like that food debate, the native versus cross-platform discussion is something nobody explicitly asked for. No further technical arguments, platform details, or conclusions are included in the excerpt.
Domain Layer Gerçekten Şart mı? 3 Satırlık UseCase’lerin Peşinde
Medium Kotlin作者:Bahadireray發布:11-02 11:31
Do We Really Need a Domain Layer? In Search of Three-Line UseCases
Putting a UseCase in front of every repository function is not architecture; sometimes it is just more folders.
重點摘要
Questions whether every repository call needs a UseCase wrapper
Suggests that extra layers can become folder overhead rather than architecture
Raises the possibility of calling the ViewModel directly
展開詳細摘要
The article questions whether a separate domain layer is truly necessary in every Kotlin app. It argues that placing a UseCase in front of every repository function is not automatically architecture; sometimes it only adds more folders and indirection. The author then points toward a simpler alternative, asking whether the ViewModel could call into the data layer directly instead of routing everything through tiny three-line UseCases. The piece is framed as a practical challenge to over-layering, not as a claim that domain separation is always wrong.
Understanding MVVM in Android with Kotlin: A Beginner-Friendly Guide
Medium Kotlin作者:Salunkhesonali發布:11-02 12:58
Understanding MVVM in Android with Kotlin: A Beginner-Friendly Guide
Learn how Model, View, and ViewModel work together to build clean, maintainable Android applications.
重點摘要
Explains the MVVM pattern in Android
Shows how Model, View, and ViewModel relate
Focuses on clean, maintainable app architecture
展開詳細摘要
This article introduces MVVM for Android development with Kotlin in a beginner-friendly way. It explains how Model, View, and ViewModel work together and frames the pattern as a way to build cleaner, more maintainable Android applications. The piece is presented as a guide for readers who want to understand the basic role of each component and how the architecture fits into Android app design.
Discusses source sets, compilation targets, and dependency sharing
展開詳細摘要
This article focuses on Kotlin Multiplatform project organization, especially the relationship between commonMain and platform-specific source sets. It highlights the core building blocks involved in KMP architecture, including source sets, compilation targets, hierarchy templates, and dependency sharing. The piece is framed as a practical guide for understanding how multiplatform code is structured across shared and platform-specific layers.
A must-read for Android developers sharing code across platforms.
重點摘要
Focuses on Kotlin 2.4.20’s Swift export improvements.
Targets better interoperability with iOS.
Aimed at Android developers who share code.
展開詳細摘要
This article points Android developers to Kotlin 2.4.20’s Swift export improvements, which are presented as a reason to pay attention if you share code across platforms. The provided text is brief and does not include technical details, benchmarks, or implementation specifics, so the safest takeaway is simply that the piece highlights iOS interoperability in this Kotlin release.
Getting ready to upgrade my side project to the latest version of Compose and was expecting a lot of errors. Turns out nothing broke.
重點摘要
Upgrade to the latest Compose version without major breakage.
The author expected many errors but encountered none.
The article is a short Medium post about the update experience.
展開詳細摘要
The author says they were preparing to upgrade a side project to the latest version of Compose and expected to run into many errors, but the update did not break anything. The post is a brief Medium note rather than a technical deep dive, and it mainly conveys relief that the migration was smooth. No specific fixes, APIs, or compatibility issues are described in the provided text.
Jetpack Compose 1.13 修复了让我烦恼的问题
我正准备把自己的 side project 升级到最新版本的 Compose,原本以为会出现很多错误;结果什么都没坏。
重點摘要
升级到最新的 Compose 版本没有造成明显破坏。
作者原本预计会遇到很多错误,但实际并没有。
这篇文章主要是在分享升级体验。
展開詳細摘要
作者表示,他在准备把自己的 side project 升级到最新版本的 Compose 时,原本预期会遇到很多错误,但实际并没有任何内容损坏。本文只是 Medium 上的一则简短感想,核心信息是升级过程出乎意料地顺利,让人松了一口气;给出的正文并未说明具体修复项、API 变化或兼容性问题。
Jetpack Compose 1.13 修正了讓我困擾的問題
我正準備把我的 side project 升級到最新版本的 Compose,原本以為會出現很多錯誤;結果什麼都沒壞。
重點摘要
升級到最新的 Compose 版本沒有造成重大破壞。
作者原本預期會出現很多錯誤,但實際上沒有。
這篇文章主要是在分享升級過程的感受。
展開詳細摘要
作者表示,他在準備把自己的 side project 升級到最新版本的 Compose 時,原本預期會遇到很多錯誤,但實際上沒有任何東西壞掉。這篇內容只是 Medium 上的一則簡短心得,重點在於升級過程出乎意料地順利,帶來鬆了一口氣的感受;提供的內文並沒有列出具體修正項目、API 變動或相容性問題。
Gradle Isolated Projects: What Breaks, and What Replaces It
Medium Kotlin作者:Ramadan Sayed發布:11-02 14:01
Gradle Isolated Projects: What Breaks, and What Replaces It
Every large Gradle build has the same two habits: an allprojects block at the root, and at least one place where one module reaches across.
重點摘要
Large Gradle builds often rely on a root-level allprojects block.
Modules frequently reach across boundaries to access each other directly.
The article examines what breaks under Isolated Projects and what can replace it.
展開詳細摘要
The article points out two common patterns in large Gradle builds: a root-level allprojects block and cross-module reach-ins. It frames the discussion around Gradle Isolated Projects, focusing on what these patterns break and what alternatives may replace them. The content is limited in the provided excerpt, so it does not claim specific implementations or results beyond the article’s stated topic.
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 features I want to see in a future Android version!
Few years ago I would promise myself I wouldn’t get too excited about another Android version.
重點摘要
The author says they used to avoid getting too excited about new Android releases.
The article is about features the author wants to see in a future Android version.
The preview period has started, but the linked text continues on Medium.
展開詳細摘要
The article is framed as a personal take on Android’s next release cycle. The author says that a few years ago they would have promised themselves not to get overly excited about another Android version, but that feeling changes when the previews begin rolling out. The excerpt does not list the features yet; it only sets up an upcoming discussion of what the author hopes to see in a future Android version, with the rest of the piece continuing on Medium.
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 Has Released, and 1.13 Is Already in Motion
What’s New, What’s Coming in Beta, and What You Should Check Before Upgrading
重點摘要
Jetpack Compose 1.12 is now available.
1.13 is already moving forward in beta.
The article points readers to things to verify before upgrading.
展開詳細摘要
Jetpack Compose 1.12 has been released, and work on 1.13 is already underway. The article frames the update around three practical angles: what is new in the current release, what is coming in beta for the next version, and what developers should review before upgrading. It does not provide the full technical details in the excerpt, but it clearly signals a transition from one stable release to the next and encourages readers to check compatibility and upgrade considerations before moving forward.
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
Migrating a Real Android App to Kotlin Multiplatform 2/4 — What Moved for Free, and What Hurt
Part 2: What Moved for Free, and What Hurt
重點摘要
Part 2 focuses on the migration experience after moving a real Android app to Kotlin Multiplatform.
It contrasts what transferred with little effort and what introduced friction.
The article continues the author's practical migration series on ProAndroidDev.
展開詳細摘要
This is the second part of a series about migrating a real Android app to Kotlin Multiplatform. The article centers on two sides of the transition: the pieces that moved over with little effort and the areas that caused pain during migration. Based on the available text, it frames the discussion as a practical follow-up in the author’s ongoing series, rather than a broad tutorial or a claim of universal success. The piece continues on ProAndroidDev and is positioned as part 2 of 4.
Java Virtual Threads vs Kotlin Coroutines: Suspension Models and the Shifting Bottleneck
Dev.to Kotlin作者:Yongho Hwang發布:11-02 00:51
Java Virtual Threads vs Kotlin Coroutines: Suspension Models and the Shifting Bottleneck
Both approaches only lower the cost of waiting; neither increases the total amount of resources.
重點摘要
Virtual threads keep suspension out of the source code, while coroutines make it explicit with suspend.
The bottleneck shifts from threads to downstream resources such as database connections.
ThreadLocal behavior changes: caching benefits can disappear, while context handling and memory costs shift at runtime.
展開詳細摘要
This article compares Java virtual threads and Kotlin coroutines through the lens of suspension mechanics rather than basic usage. Virtual threads are stackful: the runtime saves and restores the whole stack, so suspension stays invisible in code. Coroutines are stackless: the compiler rewrites suspend functions to return and later resume via a Continuation, which makes suspension explicit. The author argues that both approaches only reduce the cost of waiting, not the total demand for resources. As thread limits disappear, the bottleneck shifts to connection pools, external APIs, or disks. The post also contrasts their impact on ThreadLocal, pinning, blocking I/O, observability, and version choices, concluding that the right model depends on whether you want transparent compatibility or explicit asynchronous structure.
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
Your Compose Screenshot Tests Never Run at fontScale 1.3 — and That's Where Your Layout Breaks
Most Compose screenshot setups render each preview through one fixed device config, so they never exercise the fontScale values users actually use.
重點摘要
Most screenshot tests only render at fontScale 1.0, leaving accessibility scaling untested.
A fixed-width price label can clip at fontScale 1.3 without any crash or test failure.
Parameterize deviceConfig or LocalDensity to add a large-font variant for risky layouts.
展開詳細摘要
The article explains that many Compose screenshot test suites only render at the default fontScale 1.0, which leaves a blind spot for accessibility text scaling. A layout that looks fine in snapshots can break when users increase system font size to 1.3x or beyond, especially when a weighted text element sits beside a fixed-width sibling such as a price label. The author shows how a value like $1,249.00 can be silently truncated by TextOverflow.Ellipsis with no crash and no failing test. The recommended fix is to add a fontScale 1.3f render path by parameterizing Paparazzi DeviceConfig or overriding LocalDensity in Compose UI tests.
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
Building an Android AI Agent, Part 12: AgentContext — Knowing What the User Is Doing Before They Ask
The agent should already have a working model of the current context: which app is active, what the user was doing before the interrupt, and what they were likely about to do next.
重點摘要
AgentContext tracks active and previous apps, recent switches, pending tasks, and confidence.
App-switch patterns help infer likely user intent before the user says anything.
Confidence levels control whether the agent auto-fills, suggests, or asks explicitly.
展開詳細摘要
This part introduces AgentContext, a session-local working model that helps an Android AI agent anticipate what the user is doing before they ask for help. It stores the active and previous packages, recent app switches, the current screen snapshot, pending tasks, last known intent, and a confidence level. The builder infers confidence from recent accessibility events: frequent app switching in the last minute suggests HIGH confidence, while sparse or absent activity lowers it. The context is serialized into a compact prompt for the LLM, using only the most recent app switches and the current screen state. The agent then adapts its initial prompt behavior based on confidence, auto-filling context at HIGH, suggesting and confirming at MEDIUM, and asking directly only at LOW. Context is never persisted across sessions and becomes stale after five minutes.
构建 Android AI Agent,第 12 部:AgentContext——在用户开口前先知道他们在做什么
Why Editing a Transaction In-Place Is the Fastest Way to Corrupt Your Ledger
Dev.to Kotlin作者:DEVANSHU PATIL發布:11-02 04:30
Why Editing a Transaction In-Place Is the Fastest Way to Corrupt Your Ledger
FinLedger avoids in-place SQL updates by reversing the original postings first, then applying the edited transaction atomically.
重點摘要
In-place transaction edits can leave account balances out of sync with reality.
FinLedger uses a two-phase reconcile flow: inverse the original postings, then apply the new ones.
Room's withTransaction ensures the entire edit either commits fully or rolls back safely.
展開詳細摘要
The article explains why personal finance apps cannot treat transaction edits like ordinary CRUD updates. Changing a transaction in place can break account balances because the original economic effects have already been recorded elsewhere in the ledger. FinLedger instead uses a two-phase reconciliation approach: it first reverses the original postings, then validates and applies the updated transaction, all inside a single SQLite transaction via Room's withTransaction. This preserves balance integrity even when edits change the amount, account, transaction type, or date across billing boundaries. The post also notes that atomic rollback protects the ledger if any error or interruption occurs during the edit.
I built QuickTube, an open-source Android video & music downloader in Jetpack Compose
Dev.to Kotlin作者:Asadullah Hil Galib發布:11-02 06:39
I built QuickTube, an open-source Android video and music downloader in Jetpack Compose
QuickTube lets you search, watch, and save videos and music without ads or accounts.
重點摘要
Search and watch YouTube with live suggestions, feeds, comments, and an inline player.
Download from YouTube and 1,800+ other sites, or save audio only as M4A / Opus.
Includes share-to-download, built-in browser detection, batch downloads, and background playback.
展開詳細摘要
QuickTube is an open-source Android app built in Jetpack Compose for searching, watching, and saving videos and music without ads or accounts. It supports YouTube search and playback with live suggestions, trending and music feeds, comments, and an inline player. The app can download from YouTube and more than 1,800 other sites in multiple qualities, or as audio only. It also integrates with Android share sheets, includes a built-in browser that detects videos on a page, and supports playlists, channels, background playback, a downloads gallery, and themes. The author highlights technical work such as on-device merging without re-encoding, HLS to MP4 conversion, and extracting player data from WebView pages.
Android MVI Architecture with MVIStateStore: A Complete Guide
Dev.to Kotlin作者:StudyInPark發布:11-02 06:59
Android MVI Architecture with MVIStateStore: A Complete Guide
A comprehensive guide to building MVI with Jetpack Compose, Kotlin Coroutines/Flow, and a centralized MviStateStore.
重點摘要
Unidirectional Data Flow for a predictable state pipeline
A single immutable UiState as the source of truth
Pure reducers and coroutine channels for state and one-time side effects
展開詳細摘要
This guide explains how to build an Android MVI architecture using Jetpack Compose, Kotlin Coroutines/Flow, and a centralized MviStateStore. It focuses on unidirectional data flow, a single immutable UiState as the source of truth, and pure reducer functions for synchronous, thread-safe state transitions. It also covers handling one-time side effects such as navigation, toasts, and snackbars with Coroutine Channels to avoid re-firing issues after screen rotation, and includes a side-by-side comparison of MVI and MVVM with full Kotlin code examples.
Day 10 of 12-Day Android Interview Preparation Plan
Medium Kotlin作者:Ishant發布:11-02 00:13
Day 10 of the 12-Day Android Interview Preparation Plan
Performance Optimization and Android Internals
重點摘要
Focus on Android performance tuning
Covers Android internals
Part of a 12-day interview preparation plan
展開詳細摘要
This entry is Day 10 of a 12-day Android interview preparation plan and centers on performance optimization and Android internals. The provided content is very brief, so it mainly indicates the topic rather than offering detailed explanations or examples. It continues the interview-prep series and points readers to the full article on Medium.
Race, Queue, or Cancel: Choosing the Right flatMap for Your Kotlin Flow
Medium Kotlin作者:Android Expert發布:11-02 05:07
Race, Queue, or Cancel: Choosing the Right flatMap for Your Kotlin Flow
How flatMapMerge, flatMapConcat and flatMapLatest differ on the same input, and the production failure modes each one hides.
重點摘要
Compares flatMapMerge, flatMapConcat, and flatMapLatest on identical input.
Focuses on the behavioral differences that matter in real Kotlin Flow usage.
Highlights the production failure modes each operator can conceal.
展開詳細摘要
This article examines how flatMapMerge, flatMapConcat, and flatMapLatest behave when applied to the same input in Kotlin Flow. Rather than treating them as interchangeable, it frames the choice as a tradeoff between racing, queuing, and canceling upstream work. The piece also points out that each operator can mask different failure modes in production, making it important to understand their semantics before choosing one for an application.
Your Tests Are Green. Are They Actually Catching Bugs?
Medium Kotlin作者:Rahul Dhanuka發布:11-02 06:40
Your Tests Are Green. Are They Actually Catching Bugs?
A practical guide to mutation testing in Kotlin with PIT — from first run to CI, with a real-world scenario and interview questions.
重點摘要
Introduces mutation testing in Kotlin with PIT
Covers the workflow from first run to CI
Includes a real-world scenario and interview questions
展開詳細摘要
This article presents a practical guide to mutation testing in Kotlin using PIT. It frames the topic around a familiar concern for engineers: green tests do not always mean the tests are effective at catching bugs. The piece promises to walk through mutation testing from the first execution to CI integration, and it also references a real-world scenario plus interview questions. Based on the provided text, the article is an introduction to the approach rather than a claim of results or performance gains.
Composition Over Inheritance in Android ViewModels: Stop Writing BaseViewModel
Medium Kotlin作者:Aslam Hossin發布:11-02 07:01
Composition Over Inheritance in Android ViewModels: Stop Writing BaseViewModel
How Kotlin interface delegation and Lifecycle 2.11 scoping replace bloated 500-line base classes.
重點摘要
Kotlin interface delegation is used to favor composition over inheritance.
Lifecycle 2.11 scoping is part of the approach.
The article argues against oversized BaseViewModel classes.
展開詳細摘要
This post argues that Android ViewModels should favor composition over inheritance instead of relying on large shared base classes. It points to Kotlin interface delegation and Lifecycle 2.11 scoping as the mechanisms that can replace bloated BaseViewModel designs. The article’s emphasis is on reducing the need for massive 500-line base classes and structuring ViewModels through smaller, more focused components.