← 回到首頁

每日新聞摘要

2025年12月09日

選擇語言 / Select Language

中文 English 简体中文
今日收集到 29 篇文章摘要

Introduction to Hermes Message Broker

Introduction to Hermes Message Broker
Hermes is a message broker built on top of Apache Kafka that exposes a simple, HTTP-centric API so clients can publish and receive messages without heavy dependencies.

重點摘要

HTTP-centric broker layered on Apache Kafka for minimal client dependencies
Components: Management (UI), Frontend (publish), Consumers (deliver); requires Kafka and Zookeeper
Publish via HTTP POST or Java client; delivery semantics: 2xx/4xx = delivered, 5xx = retry
Hermes is an HTTP-centric message broker that runs on top of Apache Kafka, providing a lightweight interface for publishing and receiving messages without requiring clients to understand Kafka. Its architecture comprises Management (UI for groups, topics and subscriptions), Frontend (accepts publish requests) and Consumers (deliver messages to endpoints), and it depends on Kafka and Zookeeper. Allegro supplies Docker images and a Docker Compose example for quick testing. Topics are organized into groups and have metadata such as name, owner, Kafka ACK level and content type. Subscriptions define endpoints, delivery type, rate limits and in-flight limits and can replay retained messages. Messages are published via HTTP POST to /topics/{fully.qualified.name} (returning 202 and Hermes-Message-Id) or via a Java client; consumers receive POSTs to registered endpoints, with 2xx/4xx considered delivered and 5xx triggering retries. Hermes emphasizes reliability and easy scaling.
Hermes 消息代理简介
Hermes 建立在 Apache Kafka 之上,提供以 HTTP 为中心的简单接口,让客户端无需深入了解底层系统即可发出和接收消息。

重點摘要

基于 Kafka 的 HTTP 中心化轻量消息代理
组件包含 Management(管理界面)、Frontend(发布入口)、Consumers(投递),需 Kafka 与 Zookeeper
支持通过 HTTP POST 或 Java 客户端发布;2xx/4xx 视为已投递,5xx 会触发重试
Hermes 是一个建立在 Apache Kafka 之上的 HTTP 中心化消息代理,允许客户端通过标准 HTTP 请求或 Hermes Java 客户端轻松发布和接收消息,无需了解底层消息基础设施。体系由 Management(用于管理群组、主题与订阅)、Frontend(接受发布请求)和 Consumers(将消息发送至订阅端点)等组件构成,并依赖 Kafka 与 Zookeeper。Allegro 提供 Docker 镜像与 Docker Compose 示例以便快速测试。主题(topics)归属群组,拥有名称、所有者、Kafka ACK 等配置;订阅(subscriptions)定义接收端点、投递类型、速率限制与在途消息上限,并能回放保留期内的消息。发布到 /topics/{完整主题名} 的 HTTP POST 会返回 202 与 Hermes-Message-Id,消费者通过注册的 HTTP POST 接收消息,2xx/4xx 视作已投递,5xx 则可能重试。Hermes 强调可靠性与易扩展性。
Hermes 訊息代理簡介
Hermes 建立在 Apache Kafka 之上,提供以 HTTP 為中心的簡單介面,讓客戶端在不需理解底層系統的情況下發佈與接收訊息。

重點摘要

以 HTTP 為中心、建立在 Kafka 之上的輕量訊息代理
主要元件:Management(管理介面)、Frontend(發佈)、Consumers(送達),需 Kafka 與 Zookeeper
支援 HTTP POST 與 Java 客戶端發佈;2xx/4xx 視為已交付,5xx 會重試
Hermes 是一個建立在 Apache Kafka 之上的 HTTP 中心化訊息代理,讓應用以簡單的 HTTP 呼叫或 Hermes Java 客戶端發佈與接收訊息,減少對底層訊息基礎設施的依賴。系統包含 Management(管理群組、主題與訂閱的介面)、Frontend(接收發佈請求)與 Consumers(將訊息傳送到訂閱端點),並需搭配 Kafka 與 Zookeeper。Allegro 提供 Docker 映像與 Docker Compose 範例快速啟動,便於測試。topics 在群組下管理並含有名稱、擁有者、Kafka ACK 與內容類型等設定;subscriptions 指定送達端點、傳遞模式、速率與在途數限制,且可回放保留期間內的訊息。透過 /topics/{完整主題名稱} 的 HTTP POST 或 Java 客戶端發佈,系統回傳 202 與 Hermes-Message-Id;消費端以 HTTP POST 接收訊息,遇 2xx/4xx 視為已交付,5xx 則會觸發重試。Hermes 強調可靠性與可擴充性。

Reduce Object Header Size and Save Memory in Java 25

Reduce Object Header Size and Save Memory in Java 25
JEP 519 makes Compact Object Headers a product feature in Java 25, shrinking object headers to 8 bytes to reduce heap usage and GC pressure.

重點摘要

JEP 519 promotes Compact Object Headers from experimental to product status in JDK 25
Headers are compacted to a 64-bit layout using compressed class pointers and packed mark word fields
Smaller headers reduce heap usage, improve data locality and lower garbage-collection pressure
JEP 519 finalizes Compact Object Headers for Java 25, building on JEP 450 from Java 24 to make a compact 64-bit (8‑byte) object header the standard layout on 64‑bit platforms. The compact layout subsumes a compressed class pointer into the mark word, reduces class pointer encoding to about 22 bits, and preserves identity hash, GC age, tags and locking bits. Locking paths are simplified (legacy stack-locking removed), GC forwarding uses self‑forwarding bits and a 42‑bit forwarding address, and compressed class pointers are required (limiting class count but adequate for typical apps). Enabling flags moved from experimental to product; benefits include ~10–20% lower live-data memory for object‑heavy workloads, improved cache locality and reduced GC frequency/latency. Benchmarks show notable heap and CPU gains (e.g., SPECjbb2015 results). Risks include header‑bit exhaustion, JVMCI incompatibility, and the need for extensive testing.
在 Java 25 缩减对象头大小并节省内存
JEP 519 将 Compact Object Headers 设为 Java 25 的正式功能,将对象头压缩为 8 字节以降低堆内存占用和 GC 压力。

重點摘要

JEP 519 将 Compact Object Headers 从实验性提升为产品特性
通过将压缩类指针并入 mark word,实现 64 位(8 字节)对象头
更小的对象头降低堆占用、改善数据局部性并减少垃圾回收频率
JEP 519 在 Java 25 中将 Compact Object Headers 正式化,基于 Java 24 的 JEP 450,将对象头在 64 位平台上缩减到 64 位(8 字节)。该方案把压缩类指针编码并入 mark word,保留哈希码、GC 年龄与锁位等信息,并将类指针编码降至约 22 位以节省空间。锁机制与 GC 转发做了相应调整(移除旧的 stack-locking 路径,使用自我转发位和低 42 位地址),且要求启用压缩类指针。对小对象密集的应用,常驻数据内存可减少约 10–20%,提升缓存利用率并降低 GC 负载。风险包括标头位不足、JVMCI 不兼容及需大量测试验证。
在 Java 25 減小物件標頭大小並節省記憶體
JEP 519 將 Compact Object Headers 轉為 Java 25 的正式功能,將物件標頭壓縮為 8 位元組以降低堆記憶體與 GC 壓力。

重點摘要

JEP 519 將 Compact Object Headers 從實驗性功能提升為產品功能
透過將類指標壓縮並併入 mark word,物件標頭縮至 64 位元(8 bytes)
較小的標頭可降低堆使用、提升快取命中與減少垃圾回收頻率
JEP 519 在 Java 25 中確立了 Compact Object Headers,延續 Java 24 的 JEP 450,將物件標頭在 64 位元平台上統一為 64 位(8 字元組)布局。新布局把壓縮類指標編碼併入 mark word,保留雜湊碼、GC 年齡、標記與鎖定位元,並將類指標編碼縮至約 22 位元。輕量與重量級鎖變更、GC 轉發採用自我轉發位元與低位元位址保存,且必須啟用壓縮類指標。對象密集應用可見約 10–20% 的常駐資料記憶體下降,並提升資料局部性與降低 GC 延遲。風險包括標頭位元可能耗盡、JVMCI 兼容性問題,以及需要廣泛測試與基準驗證。

Dapr Workflows With PubSub

Dapr Workflows With PubSub
Dapr Workflows provides durable, replayable orchestration that integrates with PubSub, state, and service invocation to manage complex, long-running processes.

重點摘要

Durable execution with automatic state persistence and replay
Workflows-as-code using activities to encapsulate external I/O
Test and run workflows with Testcontainers and managed Dapr (Diagrid Catalyst)
This tutorial extends a Dapr + PubSub ride-hailing example by adding Dapr Workflows to orchestrate complex, long-running, and durable processes. It explains the durable execution model—automatic state persistence, workflow replay, and centralized retry policies—so multi-step flows (validate driver, calculate fare, notify passenger, wait for confirmation) can resume after failures without losing progress. Workflows are implemented in Spring Boot as code: deterministic workflow logic calls activities (the only place to perform external I/O) and uses the workflow context to wait for events or raise events. The guide shows starting workflows via REST or PubSub events, creating activities for validation, fare calculation, and notification, and testing happy and unhappy paths with Testcontainers. It also covers retry policies and running the app in a managed Dapr environment using Diagrid Catalyst.
使用 Dapr Workflows 与 PubSub
Dapr Workflows 提供可持久化且可重放的编排,与 PubSub、状态管理和服务调用整合以处理复杂长时程流程。

重點摘要

每步自动持久化状态并支持重放以恢复进度
以工作流代码与活动封装外部 I/O,确保决定性
使用 Testcontainers 测试流程,并可在 Diagrid Catalyst 上运行
本文在先前的 Dapr + PubSub 用例上引入 Dapr Workflows,用于编排复杂且需持久化的多步骤长时程流程。介绍耐久执行的要点:步骤后自动持久化状态、重启时重放工作流代码(使用已持久化的结果避免重复执行)以及统一的重试策略,使如验证司机、计算车费、通知乘客与等待确认等流程能在失败或重启后无缝继续。示例使用 Spring Boot 以程式码定义工作流与活动,活动负责外部 I/O,工作流保持决定性。文章还展示透过 REST 或 PubSub 发起工作流、使用 Testcontainers 测试正常与异常情境、定义重试策略,以及在 Diagrid Catalyst 托管的 Dapr 环境中运行应用的流程。
使用 Dapr Workflows 結合 PubSub
Dapr Workflows 提供可持久化與可重放的流程編排,能與 PubSub、狀態管理和服務呼叫整合以處理複雜長時程流程。

重點摘要

每步驟自動持久化狀態並支援重放以恢復進度
以工作流程式碼與活動封裝外部 I/O,維持決定性
透過 Testcontainers 測試流程,並可在 Diagrid Catalyst 上執行
本文在先前的 Dapr + PubSub 託派範例上加入 Dapr Workflows,以編排需持久化的多步驟長時程流程。說明 Dapr 的耐久執行機制(步驟後自動儲存狀態、流程重放與統一重試策略),使如驗證司機、估價、通知乘客與等待確認等步驟在失敗或重啟後能無縫恢復。示範在 Spring Boot 中以程式碼定義工作流與活動:工作流保持決定性、將 I/O 放入活動、並使用上下文等待或觸發外部事件。文章也示範如何以 REST 或 PubSub 觸發工作流、撰寫測試(含正常與錯誤場景),以及如何在 Diagrid Catalyst 的託管 Dapr 環境中執行應用。

How to Manage the java.io.IOException: Invalid Keystore Format Error

How to Manage the java.io.IOException: Invalid Keystore Format Error
The error means Java is reading a file whose structure doesn't match the expected keystore format, often due to wrong file type, incorrect KeyStore setting, corruption, or build filtering.

重點摘要

File extension or format mismatch (e.g., PKCS#12 renamed .jks)
Incorrect KeyStore type configured in code
File corruption or build tools applying text filtering
The java.io.IOException: Invalid keystore format error occurs when Java attempts to read a file that doesn’t match the expected keystore structure. Common causes include incorrect file extensions (for example a PEM or PKCS#12 file renamed to .jks), using the wrong KeyStore type in code (e.g., loading a PKCS#12 file as JKS), corruption during transfer or storage, and build tools or differing JDK/keytool versions that modify binary files. Diagnose the problem with keytool -list -v to reproduce the error and see stack traces, openssl pkcs12 -info to detect PKCS#12 containers, and by checking build resource filtering. Fixes include using the correct KeyStore.getInstance("PKCS12") or "JKS" in code, converting formats with keytool -importkeystore, ensuring binary-safe transfers, and re-exporting or recreating corrupted keystores. Maintaining consistent Java environments and disabling text filtering prevents many issues.
如何处理 java.io.IOException: Invalid keystore format 错误
该错误表示 Java 读取的文件结构与预期的密钥库格式不匹配,常由文件类型错误、KeyStore 配置不当、文件损坏或构建工具改写导致。

重點摘要

文件副檔名或格式不匹配(如将 PKCS#12 重命名为 .jks)
代码中配置了错误的 KeyStore 类型
传输损坏或构建工具对二进制文件应用文本过滤
java.io.IOException: Invalid keystore format 错误表明 Java 正在读取的文件并非其期望的密钥库格式。常见原因有错误的文件扩展名(例如将 PEM 或 PKCS#12 改为 .jks)、代码中使用了错误的 KeyStore 类型、文件在传输或存储过程中损坏,以及 Maven/Gradle 等构建工具或不同的 JDK/keytool 版本对二进制文件的处理造成改变。排查可用 keytool -list -v 复现并查看堆栈信息,使用 openssl pkcs12 -info 确认是否为 PKCS#12,检查构建配置以关闭资源文本过滤。解决办法包括在代码中使用正确的 KeyStore.getInstance("PKCS12") 或 "JKS"、用 keytool -importkeystore 转换格式、确保以二进制模式传输或重新导出密钥库,并保持一致的 Java 环境以避免兼容性问题。
如何處理 java.io.IOException: Invalid keystore format 錯誤
此錯誤表示 Java 嘗試讀取的檔案結構與預期的金鑰庫格式不符,常因檔案類型錯誤、程式設定不當、檔案損毀或建置工具改寫所致。

重點摘要

檔案副檔名或格式不符(如將 PKCS#12 改名為 .jks)
程式中 KeyStore 類型設定錯誤
檔案損毀或建置工具文字過濾改變二進位內容
java.io.IOException: Invalid keystore format 錯誤代表 Java 所讀取的檔案並非預期的金鑰庫格式。常見原因包括副檔名或檔案格式錯誤(例如把 PEM 或 PKCS#12 改名為 .jks)、程式裡指定了錯誤的 KeyStore 類型、傳輸或儲存時檔案損毀,以及 Maven/Gradle 等建置工具對二進位檔案套用文字過濾或不同 JDK/keytool 版本間的不相容。診斷方法有使用 keytool -list -v 檢查、用 openssl pkcs12 -info 確認是否為 PKCS#12,以及檢查建置設定以停用資源過濾。解決方式包括在程式中使用正確的 KeyStore.getInstance("PKCS12") 或 "JKS"、用 keytool 轉換格式、以二進位模式傳輸或重新匯出檔案,並維持一致的 Java 環境以避免相容性問題。

Terminating Scanner When Input Is Complete in Java

Terminating Scanner When Input Is Complete in Java
A Scanner on System.in blocks waiting for input; pressing Return ends only the current line, not the entire input stream.

重點摘要

Scanner on System.in waits until an EOF or explicit sentinel is provided
Use OS EOF (CTRL+D / CTRL+Z) or a sentinel like "exit" to end input
Avoid closing Scanner on System.in and avoid using == for string comparison
This article explains how to stop a Java Scanner reading from System.in when input is complete. It shows that Scanner blocks waiting for input and that pressing Return ends only the current line, not the stream. Two recommended approaches are using the OS end-of-file (EOF) marker (CTRL+D on Unix/Mac, CTRL+Z on Windows) or implementing a sentinel value such as 'exit' to signal completion. The tutorial also warns against closing a Scanner on System.in because it closes the underlying stream, and advises avoiding System.exit(0) unless necessary. Common mistakes are highlighted: using == to compare strings or checking for null, which don't work for content equality. Examples include while loops with hasNextLine(), a do-while sentinel loop, and EOF handling. The article concludes that EOF and sentinel methods are most effective, with sentinel values often being more user-friendly.
在 Java 中於输入完成后终止 Scanner
Scanner 会持续等待输入;按下回车只结束当前行,并不代表结束整个输入流。

重點摘要

System.in 的 Scanner 会持续等待直到收到 EOF 或指定的哨兵值
使用系统 EOF(Unix/Mac:CTRL+D,Windows:CTRL+Z)或输入 "exit" 作为结束信号
避免关闭读取 System.in 的 Scanner,且不要用 == 比较字符串内容
本文介绍了在 Java 中如何在输入完成后终止从 System.in 读取的 Scanner。文章指出,Scanner 会阻塞等待输入,按回车只结束当前行而不是输入流的结尾。常见且有效的两种做法是使用操作系统的 EOF(Unix/Mac 上为 CTRL+D,Windows 上为 CTRL+Z)或定义哨兵值(例如 'exit')由用户显式结束。作者提醒不要随意关闭用于 System.in 的 Scanner,因为这会关闭底层输入流,同时建议尽量避免滥用 System.exit(0)。还强调了常见错误,例如用 == 比较字符串或检测 null。示例包括 hasNextLine() 循环、do-while 与哨兵模式,结论认为 EOF 与哨兵方法最可靠,哨兵通常更友好。
在 Java 中於輸入完成後終止 Scanner
Scanner 會持續等待輸入;按下 Enter 只結束當前行,並不代表結束整個輸入串流。

重點摘要

System.in 的 Scanner 會持續等待直到收到 EOF 或指定的哨兵值
可使用系統 EOF(Unix/Mac:CTRL+D,Windows:CTRL+Z)或輸入 "exit" 類哨兵結束
避免關閉讀取 System.in 的 Scanner,且勿用 == 比較字串
本文說明在 Java 中如何在輸入完成後終止從 System.in 讀取的 Scanner。說明 Scanner 會持續等待輸入、按下 Enter 只結束該行而非整個資料流。兩種實務方法為使用作業系統的 EOF(Unix/Mac:CTRL+D,Windows:CTRL+Z)或採用哨兵值(例如 'exit')來顯式結束。文中提醒不要在讀取 System.in 時隨意關閉 Scanner,因為會關閉底層輸入流,並建議避免濫用 System.exit(0)。也指出常見錯誤,如用 == 比較字串或檢查 null。示例包含 hasNextLine() 迴圈、do-while 與哨兵模式,結論認為 EOF 與哨兵最有效,哨兵較友善。

Fixing Bean Creation Issues With MapStruct @Mapper Annotations in Spring Applications

Fixing Bean Creation Issues With MapStruct @Mapper Annotations in Spring Applications
MapStruct generates mapper implementations at compile time, and if Spring doesn't detect them, bean creation fails and injection triggers NoSuchBeanDefinitionException.

重點摘要

MapStruct produces implementations at compile time, not as Spring beans by default.
Use @Mapper(componentModel = "spring") and enable annotation processing to register mappers.
Common pitfalls: package scanning, Lombok processor order, and IDE annotation-processing settings.
MapStruct creates concrete mapper implementations during compilation, but those generated classes are plain Java classes unless configured for Spring. If Spring cannot detect or register the generated MapperImpl classes, dependency injection fails with NoSuchBeanDefinitionException and the application may not start. To fix this, configure mappers with @Mapper(componentModel = "spring") so MapStruct adds @Component to implementations, enable annotation processing in your build tool (add mapstruct-processor to maven-compiler-plugin or Gradle annotationProcessor), and turn on annotation processing in your IDE. Also ensure mapper interfaces are in packages scanned by Spring and resolve Lombok/MapStruct processor ordering to avoid incomplete model classes. Proper component model, build and IDE settings, and correct package scanning ensure MapStruct mappers are produced and registered as Spring beans, preventing runtime bean-creation errors.
修复 Spring 应用中由 MapStruct @Mapper 注解引起的 Bean 创建问题
MapStruct 在编译期间生成 mapper 实现,如果 Spring 无法检测到这些实现,就会导致 Bean 创建失败与注入异常。

重點摘要

MapStruct 生成的实现默认不是 Spring 管理的 Bean。
使用 @Mapper(componentModel = "spring") 并开启註解处理来注册 mapper。
常见问题:包扫描范围、Lombok 与 MapStruct 的处理器顺序、IDE 的註解处理设置。
MapStruct 在编译时生成映射器(mapper)的具体实现,但生成的类默认不带 Spring 注解,导致 Spring 无法将其识别为 Bean,从而在注入时抛出 NoSuchBeanDefinitionException 并可能导致应用无法启动。解决方法包括在 @Mapper 中设置 componentModel = "spring",使生成的实现带上 @Component;在 Maven 或 Gradle 中启用 annotation processing(将 mapstruct-processor 加入编译器处理路径或 annotationProcessor 依赖);并在 IDE 中开启註解处理。同时要确认 mapper 所在包被 Spring 扫描并处理 Lombok 与 MapStruct 的处理器执行顺序,防止模型类不完整或缺失 getter/setter。正确的组件模型、构建与 IDE 配置以及包扫描设置可确保 MapStruct 的 mapper 被生成并注册为 Spring bean,避免运行时的 Bean 创建错误。
修正 Spring 應用中 MapStruct @Mapper 註解引起的 Bean 建立問題
MapStruct 在編譯期間產生 mapper 的實作,若未設定為 Spring 元件或未啟用註解處理,Spring 無法偵測到這些實作而導致注入失敗。

重點摘要

預設 MapStruct 產生的實作不是 Spring 管理的 bean。
在 @Mapper 加上 componentModel = "spring" 並啟用 annotation processing。
注意套件掃描範圍、Lombok 與 MapStruct 的處理器順序與 IDE 設定。
MapStruct 於編譯階段生成 mapper 的實作類別,但若未設定 componentModel 或未啟用註解處理,生成的 MapperImpl 並不帶有 Spring 註解,Spring 無法將其納入應用程式上下文,導致注入時出現 NoSuchBeanDefinitionException 與啟動失敗。解決方法包括在 @Mapper 加上 componentModel = "spring" 以讓生成類別帶上 @Component、在 Maven 或 Gradle 中加入並啟用 mapstruct-processor 的註解處理、以及在 IDE 中開啟註解處理。此外需確認 mapper 所在套件被 Spring 掃描、調整 Lombok 與 MapStruct 的處理器順序以避免模型類不完整。完整的設定能確保 mapper 被正確建立並註冊為 Spring bean,避免執行期的 bean 建立錯誤。

Java Weekly, Issue 623

Java Weekly, Issue 623
With JDK 26 the java.applet package is officially removed, and Spring Data's AOT repositories continue to optimize startup via build-time generation and integration with Project Leyden.

重點摘要

JDK 26 removes the java.applet package
Spring Data AOT repositories speed startup and integrate with Project Leyden
Multiple framework updates and community webinars announced
This issue of Java Weekly highlights key platform and ecosystem changes: JDK 26 officially drops the java.applet package, prompting final build-path checks. Spring Data’s AOT-generated repositories (Part 2) are explored, showing how build-time code generation for JPA, JDBC and MongoDB improves startup and enables integration with Project Leyden. The roundup also points to notable JEP previews (Lazy Constants, Structured Concurrency), Spring Tools 5 updates, and articles on migration patterns, pagination, testing, and HttpClient TLS enhancements. Multiple releases are recommended for upgrade, including Spring Cloud 2025.1.0 (Oakwood), Quarkus 3.30.0, Micronaut Core milestone releases, Hibernate Search, Elasticsearch, Grails and Conductor. Technical essays cover event-sourcing patterns (Consumers vs Processors), GraphRAG vs RAG, visitor-pattern revisits, and open-source upgrade strategies. The pick of the week is a Snyk live workshop on the OWASP Top 10 in the age of AI.
Java Weekly 第 623 期
JDK 26 正式移除 java.applet 包;Spring Data 的 AOT 仓库通过构建时代码生成改善启动,并可与 Project Leyden 集成。

重點摘要

JDK 26 移除 java.applet 包
Spring Data AOT 仓库提升启动速度并支持 Leyden 集成
汇总多个框架发布、技术文章与线上研讨会
本期概览 Java 平台与社区动态:JDK 26 正式废弃 java.applet 包,建议开发者最后检查构建路径;Spring Data AOT 仓库(第二部分)解析如何通过构建时为 JPA、JDBC 与 Mongo 生成代码以优化启动并支持 Project Leyden。文中还推荐了多篇相关内容,包括 JEP 预览(Lazy Constants、Structured Concurrency)、Spring Tools 5 的准备与改进、以及关于分页、测试、TLS 支持等实务指南。同时列出若干建议升级的版本:Spring Cloud 2025.1.0 (Oakwood)、Quarkus 3.30.0、Micronaut Core、Hibernate Search、Elasticsearch、Grails 与 Conductor。技术与随想栏目讨论事件溯源中的消费者/处理器分离、GraphRAG 与 RAG 的差异,以及开源升级策略;本周精选为 Snyk 关于 AI 时代 OWASP Top 10 的公开工作坊。
Java Weekly 第 623 期
JDK 26 正式移除 java.applet 套件;Spring Data 的 AOT 儲存庫透過建置時產生代碼提升啟動速度,並能與 Project Leyden 整合。

重點摘要

JDK 26 移除 java.applet 套件
Spring Data AOT 儲存庫提升啟動並支援 Leyden 整合
多項框架更新、技術文章與線上研討會推薦
本期匯整 Java 生態的重要更新與深度文章:JDK 26 正式捨棄 java.applet 套件,提醒開發者檢查建置路徑;Spring Data AOT 儲存庫(二)說明透過建置時生成 JPA、JDBC 與 Mongo 相關代碼來優化啟動時間,並與 Project Leyden 結合。文中並連結多篇值得閱讀的技術文章(如 Lazy Constants、Structured Concurrency 預覽、Spring Tools 5 更新等)和實務指南(分頁、測試、TLS 支援等)。同時列出建議升級的版本:Spring Cloud 2025.1.0 (Oakwood)、Quarkus 3.30.0、Micronaut、Hibernate Search、Elasticsearch、Grails 與 Conductor。技術與思考欄探討事件來源架構、RAG 類型差異與開源升級策略;本週精選為 Snyk 關於 AI 時代 OWASP Top 10 的公開工作坊。

Draw a Decent Looking Circle in Java

Draw a Decent-Looking Circle in Java
Use Java2D Shapes and Graphics2D hints to render smooth, centered, and correctly stroked circles, and use offscreen buffering for crisp small icons.

重點摘要

Extend JPanel and use Graphics2D with Ellipse2D for predictable results
Apply antialiasing, pure stroke control, and quality rendering hints
Use supersampled or hardware-compatible BufferedImage for small icons and caching
This tutorial shows how to draw high-quality circles in Java Swing by using Graphics2D and the Java2D shape APIs. It starts with a JPanel that overrides paintComponent and demonstrates using Ellipse2D for a circle, then explains dynamic sizing and centering while accounting for stroke thickness to avoid clipping. The guide covers rendering hints—antialiasing, stroke control, and rendering quality—to improve smoothness and sub-pixel accuracy, and illustrates transforms for testing. For very small icons it recommends offscreen rendering: supersampled rendering (draw larger and scale down) for maximum smoothness, and hardware-compatible BufferedImage for runtime efficiency. It also suggests caching rendered images or combining both techniques to balance visual quality and performance when drawing many small circular indicators.
在 Java 中绘制好看的圆形
使用 Java2D 的 Shapes 和 Graphics2D 渲染提示,可绘制平滑、居中且描边正确的圆形,针对小图标采用离屏缓存以提升清晰度。

重點摘要

继承 JPanel 并用 Ellipse2D 与 Graphics2D 绘制圆形
启用抗锯齿、纯描边控制和高质量渲染提示
对小图标使用超采样或硬件兼容的 BufferedImage 并进行缓存
本文讲解如何在 Java Swing 中绘制高质量圆形:通过继承 JPanel 并重写 paintComponent,使用 Ellipse2D 创建宽高相等的形状来表示圆,结合 Graphics2D 的绘制与填充。示例展示根据窗口尺寸动态计算直径并以中心点定位,同时考虑笔触延伸以避免裁切。为获得更细腻的效果,启用抗锯齿、纯描边控制和高质量渲染提示以改善曲线与子像素准确度。针对 12–24 像素的小图标,推荐离屏渲染:可用超采样(先绘制为 2× 或 3× 大小再缩小)以获得最佳平滑度,或使用硬件兼容的透明 BufferedImage 以提高绘制效率,并通过缓存复用图像在大量指示器场景下保持 UI 响应。
在 Java 中繪製好看的圓形
使用 Java2D 的 Shapes 與 Graphics2D 的渲染提示,可以畫出平滑、置中且描邊正確的圓形,對小圖示則以離屏緩存提高品質。

重點摘要

繼承 JPanel 並以 Ellipse2D 與 Graphics2D 繪製圓形
開啟抗鋸齒、純描邊控制與高品質渲染提示
對小圖示採用超採樣或硬體相容的 BufferedImage 並做快取
本文示範如何在 Java Swing 中繪製外觀良好的圓形:先建立繼承 JPanel 的元件並覆寫 paintComponent,使用 Ellipse2D 取代 drawOval 以獲得可組合且可預測的結果;透過以視窗較小邊減去內距來動態計算直徑並以中心點置中,同時考慮筆觸寬度避免邊界裁切。接著介紹 Graphics2D 的渲染提示(抗鋸齒、純描邊、渲染品質)以提升曲線和子像素準確度。針對 12–24px 的小圖示,建議以離屏緩存方式渲染:超採樣法先以較高解析度繪製再縮小,或建立硬體相容的透明 BufferedImage 以加速重複繪製,並可結合兩者取得品質與效能的平衡。

Building Debian deb Packages From Java Builds Using jdeb

Building Debian .deb Packages from Java Builds Using jdeb
Automate creation of a .deb package from a Java build using jdeb, integrated with Maven and Ant.

重點摘要

Explains DEB anatomy: debian-binary, control.tar.*, and data.tar.*
jdeb provides a self-contained Maven plugin and Ant task for cross-platform .deb creation
Example shows packaging a fat JAR to /opt, a launcher to /usr/bin, and testing with dpkg
In this tutorial Haidar Ali demonstrates how to automate creation of Debian .deb packages from Java builds using jdeb. It explains DEB anatomy — debian-binary, control.tar.*, and data.tar.* — and introduces jdeb, a self-contained library (Maven plugin and Ant task) that builds .deb files cross-platform without Debian tools. The article shows Maven configuration bound to the package phase, how to define control metadata and dataSet mappers, and gives a simple "simple-cal" example that packages a fat JAR into /opt, a launcher into /usr/bin, and creates runtime directories. It covers running mvn clean package, inspecting the resulting .deb with dpkg, and installing/testing on a Debian-based system. The Ant equivalent is also provided, showing the DebTask usage and local classpath setup. The piece concludes that jdeb simplifies producing .deb artifacts for Java projects and is available on Maven Central.
使用 jdeb 将 Java 构建打包为 Debian .deb
用 jdeb 将 Java 构建自动打包成 .deb,并示范如何在 Maven 和 Ant 中集成。

重點摘要

介绍 .deb 结构:debian-binary、control.tar.* 和 data.tar.*
jdeb 提供跨平台且自包含的 Maven 插件与 Ant 任务,无需 Debian 工具
示例将 fat JAR 放入 /opt、启动脚本放入 /usr/bin,并用 dpkg 测试安装
本文展示如何使用 jdeb 将 Java 构建自动打包为 Debian .deb。文章先介绍 .deb 的三大组成(debian-binary、control.tar.*、data.tar.*),再说明 jdeb 的特性:在 Maven 和 Ant 中提供任务、支持跨平台执行且自包含,无需依赖 UNIX 工具。以 simple-cal 为例,示范如何在 pom.xml 或 build.xml 中配置 control 目录、dataSet 与 mapper,把 fat JAR 放到 /opt、把启动脚本放到 /usr/bin,并创建运行时目录。还展示了 mvn clean package 的输出、使用 dpkg 查看与安装包的流程,以及 Ant 版的 DebTask 配置。结论是 jdeb 可简化 Java 项目的 .deb 打包与发布,且可从 Maven Central 获取。
使用 jdeb 從 Java 建置建立 Debian .deb 套件
使用 jdeb 自動將 Java 建置打包成 .deb,並示範如何整合到 Maven 與 Ant 流程中。

重點摘要

說明 .deb 結構:debian-binary、control.tar.* 與 data.tar.*
jdeb 提供跨平台且自包含的 Maven 插件與 Ant 任務,無需 Debian 工具
範例將 fat JAR 放到 /opt、啟動器放到 /usr/bin,並用 dpkg 測試安裝
本文示範如何使用 jdeb 將 Java 建置自動打包為 Debian .deb。先說明 .deb 結構(debian-binary、control.tar.*、data.tar.*),再介紹 jdeb——提供 Maven 插件與 Ant 任務、跨平台且自包含,無需 Debian 工具。以簡單的 simple-cal 範例示範 Maven 與 Ant 的設定:在 control 中定義套件元資料,透過 dataSet 與 mapper 將 fat JAR 放入 /opt、啟動腳本放入 /usr/bin,並建立執行時資料夾。說明 mvn clean package、使用 dpkg 檢視與安裝,以及在 Debian 系統測試。最後指出 jdeb 可簡化 Java 專案的 .deb 發行流程,並可於 Maven Central 取得。

Solving Hibernate SyntaxException: token ‘*’, no viable alternative at input

Solving Hibernate SyntaxException: token '*', no viable alternative at input
HQL does not accept the SQL '*' wildcard because it works with entities and properties rather than tables and columns.

重點摘要

HQL doesn't recognize the '*' wildcard used in SQL.
Using an entity alias (e.g., SELECT p FROM Person p) returns full objects.
You can omit SELECT and use FROM Person as a shorthand.
This article explains why Hibernate throws the SyntaxException "token '*', no viable alternative at input" and how to fix it. The error occurs because HQL operates on entities and their properties, not on database tables and columns, so the SQL '*' wildcard is not valid. The post demonstrates the exception using a simple Person entity and an HQL query containing SELECT * FROM Person, which causes the SyntaxException. The recommended solution is to select the entity itself, for example SELECT p FROM Person p, or to omit the SELECT clause entirely and use FROM Person. The article includes a unit test example showing the failure and a corrected test that persists a Person and retrieves it with valid HQL.
解决 Hibernate SyntaxException:token ‘*’,no viable alternative at input
HQL 不支持 SQL 的 '*' 通配符,因 HQL 面向实体与属性,而不是数据表与列。

重點摘要

在 HQL 中不能使用 SQL 的 '*' 通配符。
使用实体别名(如 SELECT p FROM Person p)可以获取完整对象。
也可以省略 SELECT,直接使用 FROM Person 作为简写。
本文解释了为何会出现 SyntaxException "token '*', no viable alternative at input",并通过示例说明如何复现与修正。问题在于 HQL 操作的是实体和属性,而不是数据库表与列,因此 SQL 中表示所有列的 '*' 在 HQL 中无效。文章用一个 Person 实体和包含 SELECT * 的 HQL 查询重现异常,然后展示正确做法:使用实体别名(SELECT p FROM Person p)或直接用 FROM Person 来省略 SELECT,从而正确获取实体列表,并附上单元测试示例展示错误与修正。
解決 Hibernate SyntaxException:token ‘*’,no viable alternative at input
HQL 不支援 SQL 的 '*' 通配符,因為 HQL 操作的是實體與屬性,而非資料表與欄位。

重點摘要

在 HQL 中無法使用 SQL 的 '*' 通配符。
使用實體別名(例如 SELECT p FROM Person p)可取得整個物件。
也可省略 SELECT,直接使用 FROM Person 作為簡寫。
本文說明為何會出現 SyntaxException "token '*', no viable alternative at input",並示範重現與修正方法。錯誤的根源在於 HQL 以實體與屬性為中心,並非以資料表與欄位為操作對象,因此 SQL 的 '*' 無法被 HQL 辨識。文章以 Person 實體與包含 SELECT * 的 HQL 查詢重現此例外,接著示範正確寫法:使用實體別名(SELECT p FROM Person p)或直接省略 SELECT 改用 FROM Person,即可正確取得實體列表。文中提供單元測試示例說明失敗與修正情形。

Convert EBCDIC to ASCII in Java

Convert EBCDIC to ASCII in Java
Decode EBCDIC bytes with a specific Cp0xx Charset into Java's Unicode String, then re-encode to ASCII or UTF-8 for modern systems.

重點摘要

Use Charset.forName with the correct EBCDIC code page (e.g., Cp037) to decode bytes.
Re-encode the decoded Java String to StandardCharsets.US_ASCII or UTF-8.
For large files, stream with InputStreamReader/OutputStreamWriter or use CharsetDecoder/CharsetEncoder.
This article explains how to convert EBCDIC-encoded data to ASCII in Java, covering differences between EBCDIC and ASCII and the practical steps needed to bridge legacy mainframe data with modern systems. It shows decoding EBCDIC byte sequences into Java's internal Unicode Strings using Charset.forName with EBCDIC code pages such as Cp037, then re-encoding that String to ASCII or UTF-8 using StandardCharsets. Examples include decoding a hard-coded byte array, a step-by-step conversion pipeline that reads EBCDIC bytes into a String and obtains US_ASCII bytes, and a file-based example using FileInputStream to read an input.ebc file. For large files the article recommends streaming with InputStreamReader and OutputStreamWriter, or using CharsetDecoder/CharsetEncoder for finer control and performance. The main takeaways are selecting the correct EBCDIC code page, decoding to Unicode, and re-encoding to the target charset to make legacy data readable and portable.
在 Java 中将 EBCDIC 转为 ASCII
使用正确的 EBCDIC 代码页(如 Cp037)将字节解码为 Java 的 Unicode 字符串,再重新编码为 ASCII 或 UTF-8。

重點摘要

通过 Charset.forName 指定 EBCDIC 代码页来解码原始字节。
将解码得到的字符串用 StandardCharsets.US_ASCII 或 UTF-8 重新编码。
处理大文件时推荐使用 InputStreamReader/OutputStreamWriter 或 CharsetDecoder/CharsetEncoder 串流。
本文介绍了如何在 Java 中将 EBCDIC 编码的数据转换为 ASCII:首先说明 EBCDIC 与 ASCII 的差异,然后示范用 Charset.forName(例如 Cp037)将 EBCDIC 字节解码为 Java 的 Unicode 字符串,再使用 StandardCharsets.US_ASCII 或 UTF-8 重新编码以便现代系统读取。文章给出小型字节数组解码、逐步的字节→字符串→ASCII 转换示例,以及用 FileInputStream 读取 input.ebc 并转换输出的完整文件示例。对于大型文件,建议使用 InputStreamReader/OutputStreamWriter 串流处理或 CharsetDecoder/CharsetEncoder 以获得更好的性能与控制。核心在于选对 EBCDIC 代码页、将字节正确解码为 Unicode,然后再编码为目标字符集以实现历史数据的可读性与可移植性。
在 Java 中將 EBCDIC 轉為 ASCII
以正確的 EBCDIC 代碼頁(例如 Cp037)解碼為 Java 的 Unicode 字串,再重新編碼為 ASCII 或 UTF-8。

重點摘要

使用 Charset.forName 指定 EBCDIC 代碼頁解碼原始位元組。
以 StandardCharsets.US_ASCII 或 UTF-8 重新編碼為現代系統可讀格式。
大檔案建議用 InputStreamReader/OutputStreamWriter 或 CharsetDecoder/CharsetEncoder 串流處理。
本文示範如何在 Java 中將 EBCDIC 編碼資料轉為 ASCII:先說明 EBCDIC 與 ASCII 的差異,然後以 Charset.forName(如 Cp037)將原始 EBCDIC 位元組解碼為 Java 的 Unicode 字串,再用 StandardCharsets.US_ASCII 或 UTF-8 重新編碼以便現代系統使用。範例包含直接解碼位元組陣列、步驟化的位元組→字串→ASCII 管線,以及從檔案讀取 input.ebc 並轉出 ASCII 的完整示例。對於大型檔案,文章建議以 InputStreamReader/OutputStreamWriter 串流或使用 CharsetDecoder/CharsetEncoder 取得效能與精細控制,重點在於選對代碼頁、正確解碼與再編碼以確保資料可讀且可移植。

Access Resources in a Quarkus Native Image

Access Resources in a Quarkus Native Image
GraalVM native images do not automatically include classpath resources, so you must explicitly configure which files are packaged into the native executable.

重點摘要

Public web files served from META-INF/resources are exposed automatically.
Use quarkus.native.resources.includes in application.properties to include classpath files via glob patterns.
For complex patterns, provide a resource-config.json under META-INF/native-image/<group-id>/<artifact-id>.
This article explains how to make file resources available to a Quarkus application compiled as a GraalVM native image. Because GraalVM does not automatically include classpath resources in the native executable, you must explicitly list the files to be bundled. The piece demonstrates three approaches: placing static public assets in META-INF/resources (automatically exposed as web content); declaring glob patterns in application.properties via quarkus.native.resources.includes to include specific files from src/main/resources; and using a resource-config.json placed under src/main/resources/META-INF/native-image/<group-id>/<artifact-id> for more advanced patterns. It shows a simple readResource method using ClassLoader.getResourceAsStream, how to expose file contents via REST endpoints, and notes that JUnit tests run in the JVM but you should build and run the native executable (mvn -Pnative) to verify resources in the actual native image.
在 Quarkus 原生镜像中访问资源
GraalVM 生成的原生镜像不会自动包含 classpath 上的资源,必须显式配置要打包的文件才能在可执行文件中使用。

重點摘要

将静态网页资源放在 META-INF/resources,Quarkus 会自动作为公开内容提供。
在 application.properties 使用 quarkus.native.resources.includes 用 glob 模式包含指定资源。
复杂匹配可通过 src/main/resources/META-INF/native-image/<group-id>/<artifact-id>/resource-config.json 配置。
本文介绍了如何在使用 GraalVM 构建的 Quarkus 原生镜像中访问文件资源。由于原生镜像不会自动把 classpath 资源包含进可执行文件,开发者需要显式声明要打包的资源。文章演示三种方式:将公开静态资源放在 META-INF/resources 以供 Web 访问;在 application.properties 中通过 quarkus.native.resources.includes 指定 glob 模式包含 src/main/resources 下的文件;以及在 META-INF/native-image/<group-id>/<artifact-id>/ 下添加 resource-config.json 来支持更复杂的匹配规则。文中还给出了使用 ClassLoader.getResourceAsStream 读取资源并通过 REST 端点暴露的示例,并建议通过 mvn -Pnative 构建并运行原生可执行文件来验证资源可用性。
在 Quarkus 原生映像中存取資源
GraalVM 建立的原生映像不會自動包含 classpath 上的資源,必須明確配置要打包的檔案才會出現在執行檔中。

重點摘要

將靜態網站資源放在 META-INF/resources,Quarkus 會自動當作網頁內容對外提供。
在 application.properties 使用 quarkus.native.resources.includes 指定 glob 模式包含資源。
複雜規則可透過 src/main/resources/META-INF/native-image/<group-id>/<artifact-id>/resource-config.json 設定。
本文示範如何在以 GraalVM 建置的 Quarkus 原生映像中存取檔案資源。說明重點在於原生映像不會自動將 classpath 資源納入,因此需明確配置。文章展示三種做法:把公開靜態檔放在 META-INF/resources 以供網頁端存取;在 application.properties 用 quarkus.native.resources.includes 指定要包含的檔案或目錄;以及在 META-INF/native-image/<group-id>/<artifact-id>/ 下放置 resource-config.json 以支援更複雜的匹配模式。範例還包含透過 ClassLoader.getResourceAsStream 讀取資源並以 REST API 回傳的程式碼片段,並提醒應以 mvn -Pnative 建置並執行原生執行檔來驗證資源是否正確包含。

Kotlin Multiplatform vs Flutter vs React Native: Which Cross-Platform Framework Should You Choose in 2026?

Kotlin Multiplatform vs Flutter vs React Native: Which Cross-Platform Framework Should You Choose in 2026?
Choosing the right framework in 2026 requires evaluating performance, UI needs, team capabilities, budget, and long-term roadmap.

重點摘要

Kotlin Multiplatform (KMP) excels at native performance and reusing shared business logic across platforms.
Flutter leads in pixel-perfect, GPU-heavy UI and smooth 120Hz animations with its Impeller 2 engine.
React Native offers fastest time-to-market via JavaScript/TypeScript talent and a modernized architecture (Fabric, TurboModules).
By 2026 three cross-platform frameworks dominate: Kotlin Multiplatform (KMP), Flutter, and React Native. KMP is mature, excels at sharing business logic across Android, iOS, desktop, web and backend, compiles to native for fastest cold starts, best on-device ML integration, and offers low energy use—ideal for enterprise, AI-driven and logic-heavy apps. Flutter, backed by Google, provides pixel-perfect, consistent UIs using its Impeller 2 engine, excels at 120Hz animation and GPU-heavy graphics, and supports AI UI generation—best for consumer apps and rich visual experiences. React Native benefits from a huge JavaScript/TypeScript talent pool and modernization (Fabric, TurboModules, React 19) for improved performance and faster time-to-market, fitting web-oriented teams and MVPs. Choose based on performance needs, UI fidelity, team skillset, budget and long-term roadmap rather than popularity alone.
Kotlin Multiplatform、Flutter 与 React Native:2026 年应该选择哪个跨平台框架?
在 2026 年,选择框架应根据性能、UI 需求、团队能力、预算与长期路线做出战略性判断。

重點摘要

KMP 强于共享业务逻辑并编译为原生以取得最佳性能与低能耗。
Flutter 以 Impeller 2 提供像素级一致 UI 与出色的 GPU 动画表现。
React Native 依靠大量 JS/TS 人才和现代化架构,适合快速上线与 MVP。
到 2026 年,Kotlin Multiplatform (KMP)、Flutter 与 React Native 成为跨平台开发的三大主流。KMP 趋于成熟,擅长在移动、桌面、Web 与后端之间共享业务逻辑,编译为原生代码带来最快的冷启动、良好的设备端机器学习整合与较低的能耗,适合企业级与逻辑密集型应用。Flutter 在视觉一致性与动画性能上领先,借助 Impeller 2 引擎支持 120Hz 动画与 GPU 密集任务,适合消费类产品或对视觉要求高的应用。React Native 受益于庞大的 JavaScript/TypeScript 人才库与 Fabric、TurboModules 等现代化改进,便于快速迭代与推出 MVP。最终应根据性能、UI 要求、团队技能和长期路线做出选择。
Kotlin Multiplatform、Flutter 與 React Native:2026 年該選哪個跨平台框架?
在 2026 年,選擇框架需依效能、UI 要求、團隊能力、預算與長期路線做出策略性判斷。

重點摘要

KMP 以共享商業邏輯與原生編譯帶來最佳效能與低能耗。
Flutter 以 Impeller 2 提供像素級一致性與極佳的 GPU 動畫表現。
React Native 倚賴大量 JS/TS 人才與現代化架構,適合快速上線的專案。
到 2026 年,Kotlin Multiplatform (KMP)、Flutter 與 React Native 成為跨平台開發的主流選項。KMP 已趨成熟,適合企業級與邏輯密集型應用,能共享商業邏輯並編譯為原生碼以獲得最快冷啟動、良好裝置端 ML 整合與能源效率。Flutter 在 UI 與動畫方面領先,透過 Impeller 2 引擎支援 120Hz 與高效 GPU 運算,適用於設計一致性與視覺要求高的消費型產品。React Native 受益於龐大的 JavaScript/TypeScript 人才庫與 Fabric、TurboModules 等現代化改進,方便快速發布 MVP 與網路導向團隊。最終選擇應以專案的效能、UI 需求、團隊技能與長期規劃為主。

Kotlin Multiplatform vs Flutter vs React Native: Which Cross-Platform Framework Should You Choose in 2026?

Kotlin Multiplatform vs Flutter vs React Native: Which Cross-Platform Framework Should You Choose in 2026?
Picking the right framework in 2026 means weighing performance, UI fidelity, team skills, budget, and long-term roadmap—not just popularity.

重點摘要

Kotlin Multiplatform: best for native performance and shared business logic
Flutter: best for pixel-perfect UIs, smooth 120Hz animations and GPU-heavy graphics
React Native: fastest market entry with large JavaScript/TypeScript talent pool
As of 2026, Kotlin Multiplatform (KMP), Flutter, and React Native are the dominant cross-platform choices, each optimized for different priorities. KMP excels at compiling shared business logic to native binaries, giving the fastest cold starts, best battery and memory efficiency, and strong on-device ML integration—ideal for enterprise, AI-driven, and logic-heavy apps. Flutter, powered by the Impeller 2 engine and Dart 3.5, delivers the most consistent, pixel-perfect UI across surfaces and superior GPU/animation performance, suited for consumer apps and high-fidelity interfaces. React Native, modernized with Fabric, TurboModules and a new JSI bridge, benefits from vast JS/TS talent and rapid MVP development, though initial load and runtime remain JS-dependent. Cost and maintenance trade-offs differ: RN offers lower initial hiring cost, Flutter balances medium initial with lower maintenance, and KMP has higher upfront native expertise needs but lower long-term maintenance. Choose based on performance needs, UI demands, team skills, and long-term platform alignment.
Kotlin Multiplatform、Flutter 与 React Native:2026 年应该选择哪个跨平台框架?
在 2026 年选择框架要基于性能、UI 需求、团队能力、预算和长期路线,而不是单看流行度。

重點摘要

KMP:原生性能与逻辑复用优势明显
Flutter:像素级一致 UI 与高帧动画表现最佳
React Native:JS/TS 人才多、适合快速上手与 MVP
截至 2026 年,Kotlin Multiplatform、Flutter 和 React Native 各有定位。KMP 以将共享业务逻辑编译为原生二进制见长,启动速度最快、功耗与内存效率最高,且与设备端 ML 整合良好,适用于企业级和 AI 驱动的复杂应用。Flutter 借助 Impeller 2 和 Dart 提供统一且高保真的 UI 表现,尤其擅长 GPU 密集型动画与 120Hz 交互,适合消费者产品与可视化仪表盘。React Native 在新架构(Fabric、TurboModules)与 JSI 桥接下性能显著提升,结合广泛的 JavaScript/TypeScript 人才与 Expo 工具,适合想快速迭代或沿用 Web 技能的团队。最终应根据性能要求、UI 重视度、团队构成和长期维护成本来决定。
Kotlin Multiplatform、Flutter 與 React Native:2026 年該選哪個跨平台框架?
在 2026 年選框架必須衡量效能、UI 要求、團隊能力、預算與長期路線圖,而非僅看流行度。

重點摘要

KMP:原生效能與共用商業邏輯最佳
Flutter:像素等級一致 UI 與 120Hz 動畫最強
React Native:Web 團隊與快速上線的首選
到了 2026 年,Kotlin Multiplatform、Flutter 和 React Native 各擅勝場。KMP 將共用商業邏輯編譯成原生碼,啟動最快、能耗與記憶體效率高,且與本地 ML 套件整合優秀,適合企業級與 AI 驅動的複雜系統。Flutter 以 Impeller 2 引擎和 Dart 提供跨平台一致且高保真 UI,尤其在 GPU 動畫與高更新率畫面表現出色,適合消費型與多媒體應用。React Native 在採用 Fabric 與 TurboModules 後性能接近原生,憑藉龐大的 JavaScript/TypeScript 人才庫與 Expo 生態,適合需要快速迭代或以 Web 技術為主的團隊。選擇依據應為效能需求、視覺一致性、開發成本與長期維運策略。

Tutorial Instalasi Android Studio dan Kotlin untuk membuat aplikasi “Hello Android”

Tutorial: Install Android Studio and Kotlin to Create a "Hello Android" App
First, install Android Studio from the official developer site and download the stable release.

重點摘要

Download and install Android Studio from the official site
Configure Android Studio for Kotlin development
Create and run a simple "Hello Android" app
Author Hadyan Kholish Prasetio provides a step-by-step tutorial for installing Android Studio and using Kotlin to create a simple “Hello Android” application. The article starts by directing readers to the official Android Studio download page (developer.android.com/studio) to get the stable release and install the IDE. After installation, the guide explains configuring Android Studio for Kotlin development, creating a new project, and adding minimal code and UI to display a “Hello Android” message. It’s aimed at beginners who need a concise, practical walkthrough to set up the development environment and run their first app on an emulator or device. The tutorial emphasizes using official tools and links to the Android developer site to ensure readers download the correct release. It assumes no prior Kotlin experience and keeps explanations practical.
Android Studio 与 Kotlin 安装教程:创建“Hello Android”应用
首先从官方开发者网站下载并安装 Android Studio 的稳定版本。

重點摘要

从官方网站下载并安装 Android Studio
在 Android Studio 中配置 Kotlin 开发环境
创建并运行简单的“Hello Android”应用
Hadyan Kholish Prasetio 的教程说明如何安装 Android Studio 并使用 Kotlin 构建一个简单的“Hello Android”应用。文章先引导读者前往官方下载页面 (developer.android.com/studio) 获取稳定版本并完成安装,随后说明在 Android Studio 中配置 Kotlin 开发环境、建立新项目,并加入最基本的代码和界面以显示“Hello Android”信息。该教程面向初学者,侧重实用的环境搭建和首次运行应用,并通过官方链接确保下载到正确的发布版本。
Android Studio 與 Kotlin 安裝教學:建立「Hello Android」應用
首先從官方開發者網站下載並安裝 Android Studio 的穩定版本。

重點摘要

從官方網站下載並安裝 Android Studio
在 Android Studio 中設定 Kotlin 開發環境
建立並執行簡單的「Hello Android」應用
Hadyan Kholish Prasetio 撰寫的教學,說明如何安裝 Android Studio 並以 Kotlin 建置一個簡單的「Hello Android」應用程式。文章先引導讀者前往官方下載頁面 (developer.android.com/studio) 取得穩定版本並完成安裝,接著說明如何在 Android Studio 中設定 Kotlin 開發環境、建立專案,並加入最簡單的程式與介面以顯示「Hello Android」訊息。本教學針對初學者,重點在於實用的環境設定與初次執行應用,並以官方網站連結確保下載正確的釋出版本。

How mocking works under the hood?

How mocking works under the hood?
A brief greeting to Kotlin developers and an invitation to continue reading the full article on Medium.

重點摘要

Article titled 'How mocking works under the hood?' by Marcin Moskala
Addresses Kotlin developers with a short greeting
Excerpt directs readers to continue reading on Medium for the full content
This entry, titled "How mocking works under the hood?", is authored by Marcin Moskala and targets Kotlin developers. The only available excerpt greets the audience with "Hello Kotliners!" and instructs readers to continue reading the full piece on Medium. The title indicates the article's focus is explaining how mocking operates beneath the surface, but the provided text does not include the substantive content or technical details. To read the full explanation and examples, the reader is directed to the Medium link. The excerpt functions as an introduction and pointer rather than a self-contained article, so interested readers must follow the link to access Marcin Moskala's full discussion on mocking internals.
模拟(mocking)在底层如何工作?
向 Kotlin 开发者问候并引导读者前往 Medium 阅读完整文章。

重點摘要

文章题为「模拟在底层如何工作?」,作者 Marcin Moskala
以「Hello Kotliners!」向 Kotlin 社区问候
摘录仅为引导,提示读者在 Medium 阅读全文
这篇由 Marcin Moskala 撰写的文章,标题为「模拟在底层如何工作?」,目标读者为 Kotlin 开发者。当前可见的摘录非常简短,仅包含对 Kotlin 社区的问候「Hello Kotliners!」并提示“Continue reading on Medium »”以获取完整内容。标题表明文章意在解释 mocking 的底层机制,但提供的片段并不包含具体技术说明或示例;它作为介绍并引导读者前往 Medium 阅读完整文章,想了解详细内容的人需访问链接查看全文。
模擬(mocking)在底層如何運作?
向 Kotlin 社群問候並引導讀者前往 Medium 閱讀全文。

重點摘要

文章標題為「模擬在底層如何運作?」,作者 Marcin Moskala
以「Hello Kotliners!」向 Kotlin 開發者致意
現有摘錄僅為導引,並引導讀者到 Medium 閱讀全文
這篇由 Marcin Moskala 撰寫的文章,標題為「模擬在底層如何運作?」,面向 Kotlin 開發者。現有公開的摘錄內容非常簡短,只包含對 Kotlin 社群的問候「Hello Kotliners!」並附上「Continue reading on Medium »」的導向。標題顯示文章重點在於說明 mocking 的底層運作原理,但目前提供的片段並未包含具體技術細節或範例;它僅作為引言與導讀,欲閱讀完整說明與細節的讀者需點擊提供的 Medium 連結以取得全文。

Optimizing Android App Performance with Kotlin Coroutines

Optimizing Android App Performance with Kotlin Coroutines
Make your Android apps smoother, faster, and more responsive with structured concurrency.

重點摘要

Adopt structured concurrency with Kotlin Coroutines
Improve app smoothness and responsiveness
Keep asynchronous work tied to component lifecycles
Kumarsamy highlights how using Kotlin Coroutines with structured concurrency can make Android apps smoother, faster, and more responsive. Structured concurrency organizes asynchronous work into clear scopes tied to component lifecycles, which simplifies task management, cancellation, and error handling. By keeping background operations predictable and bounded, coroutines reduce the risk of leaks and inconsistent states, improving UI responsiveness and overall performance. The article is a concise prompt to adopt coroutine-based patterns so background work is better coordinated with app components; readers are directed to the full Medium post for implementation examples and practical guidance on applying these patterns in real projects.
使用 Kotlin Coroutines 优化 Android 应用性能
通过结构化并发,让 Android 应用更流畅、更快速且响应更好。

重點摘要

采用 Kotlin Coroutines 的结构化并发
提升应用流畅度与响应性
将异步工作绑定到组件生命周期
作者指出,借助 Kotlin Coroutines 并采用结构化并发,可以使 Android 应用变得更顺畅、更快速和更具响应性。结构化并发将异步任务组织到清晰的作用域中并绑定到组件生命周期,从而简化任务管理、取消与错误处理,降低资源泄漏和状态不一致的风险。这种方式让后台工作更可预测、更可控,从而提升界面响应和整体性能。文章篇幅简洁,并引导读者到 Medium 查看详细实现示例和实践建议。
以 Kotlin Coroutines 優化 Android 應用效能
運用結構化併發,讓 Android 應用更順暢、更快速且更具回應性。

重點摘要

使用 Kotlin Coroutines 的結構化併發
提升應用順暢度與回應性
將非同步工作綁定於元件生命週期
作者指出,透過 Kotlin Coroutines 並採用結構化併發,可顯著改善 Android 應用的流暢度與反應速度。結構化併發將非同步任務組織到明確的作用域中,並綁定於元件生命週期,有助於簡化任務管理、取消與錯誤處理,減少資源洩漏與不一致狀態。這種做法使背景工作可預期且受控,進而提升 UI 回應性與整體效能。文章為快速導讀,並引導讀者前往 Medium 閱讀完整實作範例與最佳實務建議。

Butter-Smooth signatures in Kotlin Multiplatform: The math behind the ink

Butter-Smooth signatures in Kotlin Multiplatform: The math behind the ink
How to transform pixelated strokes into professional signatures with Bézier curves and simulated physics in Kotlin Multiplatform.

重點摘要

Use Bézier curve fitting to smooth pixelated stroke data
Simulate ink physics (pressure, speed) for realistic stroke width and flow
Implement the pipeline in Kotlin Multiplatform for cross-platform reuse
This article explains how to convert pixelated, sampled strokes into polished, professional signatures by combining Bézier curve mathematics with simulated ink physics, implemented in Kotlin Multiplatform. It outlines the core steps: sampling input points, constructing control points and Bézier interpolations to smooth the trajectory, and applying a physics-inspired model that uses velocity and pressure to modulate stroke width and ink flow. The approach balances mathematical derivation and practical engineering to preserve signature characteristics while reducing artifacts from raw touch or bitmap input. Implementing the solution in Kotlin Multiplatform enables the same logic to be reused across platforms, aiming to deliver accurate, performant digital ink suitable for signature input and other handwriting applications.
Kotlin Multiplatform 中的丝滑签名:墨迹背后的数学
演示如何用贝塞尔曲线和拟真物理模拟,将颗粒化笔迹转换为专业签名。

重點摘要

用贝塞尔曲线拟合并平滑采样笔迹
模拟速度与压力以再现笔尖宽度和墨流
通过 Kotlin Multiplatform 实现跨平台代码复用
本文示范如何将触控或点阵数据产生的颗粒化笔迹,通过贝塞尔曲线与拟真物理模拟,转成专业的签名向量。作者说明以采样点建立曲线控制点、利用贝塞尔插值平滑轨迹,并加入速度与压力相关的墨迹物理模型以模拟笔尖宽度与流量变化。整体做法兼顾数学推导与工程实现,并以 Kotlin Multiplatform 实现跨平台代码复用,兼顾准确度与性能,适用于签名输入与数字墨迹应用。
Kotlin Multiplatform 中的順滑簽名:墨跡背後的數學
示範如何以貝茲曲線與擬真物理模擬,將顆粒化筆跡轉換為專業簽名。

重點摘要

以貝茲曲線擬合並平滑取樣筆跡
模擬速度與壓力影響以重現筆尖寬度與墨流
採用 Kotlin Multiplatform 實現跨平台共用邏輯
本文示範如何將觸控或點陣資料產生的顆粒化筆跡,透過貝茲曲線與擬真物理模擬,轉換為專業的簽名向量。作者說明以取樣點建立曲線控制點、利用貝茲插值平滑軌跡,並加入速度與壓力相關的墨跡物理模型以模擬筆尖寬度與流量變化。整體做法兼顧數學推導與工程實作,並以 Kotlin Multiplatform 實現跨平台程式碼重用,兼顧準確度與效能,適用於簽名輸入與數位墨跡應用。

Complete Deep Dive: How ViewModel Works & Survives Configuration Changes

Complete Deep Dive: How ViewModel Works & Survives Configuration Changes
A complete deep dive into the internals of ViewModel, ViewModelStore, and the ActivityThread.

重點摘要

Deep dive into ViewModel internals
Examines ViewModelStore and ActivityThread
Explains how ViewModel survives configuration changes
This article presents a thorough examination of Android's ViewModel, ViewModelStore, and the ActivityThread, with the primary aim of explaining how ViewModel instances are managed and how they survive configuration changes. It focuses on internals and runtime relationships so readers can understand why ViewModels can outlive activity recreation triggered by rotations or other configuration updates. The piece clarifies the roles of the store and the thread that coordinate lifecycle-driven retention and cleanup, and highlights practical implications for app state management. Rather than high-level patterns alone, the article aims to demystify the underlying mechanisms and interactions that determine ViewModel lifetime, helping developers make predictable architecture and memory-safety decisions when relying on ViewModel for surviving configuration changes.
完整深度解析:ViewModel 如何工作并在配置更改中存活
对 ViewModel、ViewModelStore 与 ActivityThread 内部运作的全面深入解析。

重點摘要

深入解析 ViewModel 内部
审视 ViewModelStore 与 ActivityThread 的作用
解释 ViewModel 在配置变更中如何存活
本文对 Android 的 ViewModel、ViewModelStore 与 ActivityThread 进行了完整且深入的解析,核心在于说明 ViewModel 实例如何被创建、管理与回收,以及它们如何在配置变更(如屏幕旋转)导致 Activity 重建时仍然得以存活。文章着重揭示这些组件之间的运行时关系与保留行为,讨论这些内部机制对状态保持和内存管理的实际影响,帮助开发者理解为何 ViewModel 能在配置变更时保持状态,从而做出更稳健的架构与资源管理选择。
完整深入探究:ViewModel 如何運作並度過配置變更
完整深入解析 ViewModel、ViewModelStore 與 ActivityThread 的內部運作。

重點摘要

解析 ViewModel 的內部運作
說明 ViewModelStore 與 ActivityThread 的角色
說明 ViewModel 如何在配置變更中存活
本文對 Android 的 ViewModel、ViewModelStore 與 ActivityThread 進行完整且深入的探討,重點在說明 ViewModel 實例如何被管理,以及它們如何在配置變更(例如畫面旋轉)導致 Activity 重建時仍能存活。文章聚焦於內部運作與執行時關係,說明儲存與生命週期協調的角色與清理時機,並討論這些機制對應用狀態管理與記憶體安全的實際影響,協助開發者在使用 ViewModel 保持狀態時做出更可預期的架構與資源處理決策。

Mastering the R8 Metadata: Beyond the Stack Trace ️‍♂️

Mastering R8 Metadata: Beyond the Stack Trace
Use R8's hidden artifacts — full-r8-config.txt and whyareyoukeeping — to diagnose build bloat and debug minification.

重點摘要

Inspect full-r8-config.txt and whyareyoukeeping to see what R8 applied
Trace retained classes/resources to diagnose build bloat
Iterate keep rules and mappings to fix minification issues
This article explains how to use hidden R8 artifacts — full-r8-config.txt and the whyareyoukeeping reports — to go beyond stack traces when diagnosing build size and minification problems. It shows how to extract and read the full-r8-config to see what rules and inputs R8 actually applied, and how to use whyareyoukeeping output to find which code, resources or libraries are being retained and why. The piece outlines practical steps for tracing unexpected kept classes or methods, identifying configuration mistakes, and reducing “build bloat” by removing or tightening keep rules. It also covers strategies to reproduce minification bugs, interpret mapping files, and iterate on rules until the app is both smaller and functionally correct, enabling precise fixes for excessive output and broken transformations.
精通 R8 元数据:超越堆栈追踪
使用 R8 的隐藏产物——full-r8-config.txt 和 whyareyoukeeping——诊断构建臃肿并调试混淆问题。

重點摘要

查看 full-r8-config.txt 与 whyareyoukeeping 以确认 R8 的实际应用
定位被保留的类/资源以发现构建臃肿原因
调整 keep 规则与映射文件以修复混淆缺陷
本文说明如何利用 R8 的隐藏产物──full-r8-config.txt 与 whyareyoukeeping 报告──超越堆栈追踪诊断构建臃肿与混淆问题。文章示范如何提取并阅读 full-r8-config.txt,以了解 R8 实际应用的规则与输入,并使用 whyareyoukeeping 找出被保留的类、方法或资源及其原因。作者列出实务步骤追踪意外被保留的项、修正配置错误并收紧 keep 规则以减少 build bloat,同时提供重现混淆缺陷、解析映射文件与逐步调整规则的策略,让开发者能精确定位并修复过量输出与错误转换的根源。
精通 R8 Metadata:超越堆疊追蹤
利用 R8 的隱藏產物──full-r8-config.txt 與 whyareyoukeeping──來診斷編譯膨脹與調試混淆問題。

重點摘要

檢視 full-r8-config.txt 與 whyareyoukeeping 以了解 R8 實際套用內容
追蹤被保留的類別或資源以診斷 build bloat
調整 keep 規則並解析映射檔以修復混淆錯誤
本文說明如何利用 R8 的隱藏產物──full-r8-config.txt 與 whyareyoukeeping 報告──超越堆疊追蹤來診斷編譯體積與混淆問題。文章說明如何擷取並閱讀 full-r8-config.txt,以瞭解 R8 實際套用的規則與輸入,並示範如何用 whyareyoukeeping 找出被保留的類別、方法或資源及其原因。作者列出實務步驟來追蹤意外被保留的項目、修正配置錯誤並精簡 keep 規則以減少 build bloat,同時提供重現混淆錯誤、解析映射檔與逐步調整規則的策略,讓開發者能精準定位與修復過多輸出與錯誤轉換的根源。

Kotlin Flow Crash Course

Kotlin Flow Crash Course
Kotlin's Flow API has become the go-to tool for modern Android apps, offering a concise, coroutine-friendly way to handle asynchronous operations.

重點摘要

Flow is the preferred API for modern Android asynchronous work.
Offers a concise, coroutine-friendly approach to async programming.
Targets handling asynchronous data streams in Android apps.
This crash course introduces Kotlin's Flow API as a modern, coroutine-friendly solution for asynchronous programming on Android. The article positions Flow as the go-to tool for handling asynchronous operations and reactive data streams, emphasizing its concise integration with Kotlin coroutines. Readers can expect a compact primer that explains why developers adopt Flow for cleaner, coroutine-aware async code, how it fits into Android development patterns, and what benefits it brings compared with more verbose callback-based approaches. The piece aims to provide practical insight into Flow's role in modern applications and to equip readers with an understanding of its core purpose and typical usage scenarios, helping them decide when and how to adopt Flow in their projects.
Kotlin Flow 快速入门
Kotlin 的 Flow API 已成为现代 Android 应用的首选工具,提供简洁且与 coroutine 友好的方式来处理异步操作。

重點摘要

Flow 成为现代 Android 处理异步的首选 API。
以简洁且与 coroutine 兼容的方式实现异步编程。
适用于处理应用内的异步数据流。
本文以快速入门的角度介绍 Kotlin 的 Flow API,强调它作为现代 Android 应用处理中异步操作的常用工具。文章指出 Flow 与 Kotlin coroutine 的良好配合,使得异步代码更为简练且易于控制,特别适合用于反应式数据流的场景。读者可藉由此篇得到对 Flow 目标与典型使用情境的概览,了解其如何比传统的回调方式带来更清晰的结构,并据此判断在项目中何时采用 Flow 以提升代码可维护性和一致性。
Kotlin Flow 快速入門
Kotlin 的 Flow API 已成為現代 Android 應用的首選工具,提供簡潔且與 coroutine 友好的方式來處理非同步操作。

重點摘要

Flow 成為現代 Android 處理非同步的首選 API。
以簡潔且與 coroutine 相容的方式進行非同步程式設計。
適合處理應用中的非同步資料串流。
本文以「快速入門」的方式介紹 Kotlin 的 Flow API,說明其為現代 Android 應用中處理非同步工作的常用方案。文章強調 Flow 與 Kotlin coroutine 的緊密整合,使非同步程式碼更為簡潔且易於管理,適合用於反應式資料串流的處理。讀者可以從中獲得對 Flow 目的與使用情境的概覽,理解它如何改善傳統 callback 或較為冗長的非同步模式,並判斷何時在專案中導入 Flow 以提升程式碼可讀性與一致性。

Spring Data JPA Best Practices: Transactions and Manual Queries

Spring Data JPA Best Practices: Transactions and Manual Queries
Learn how to avoid issues with Spring Transactions and write clean manual queries without JPA magic.

重點摘要

Avoid common Spring Transaction pitfalls
Prefer explicit manual queries to opaque JPA behavior
Follow pragmatic best practices for reliability
This short best-practice article by Dmitry Protsenko on Level Up Coding focuses on two practical areas in Spring Data JPA: properly handling transactions and writing manual queries without relying on JPA "magic." It highlights how transactional misconfigurations or implicit JPA behavior can lead to subtle bugs, and encourages developers to use clear, explicit queries and transaction boundaries to improve predictability and maintainability. The piece positions these recommendations as pragmatic practices to avoid surprises in production systems, emphasizing clarity over implicit framework behavior. Readers are invited to follow the article for concrete tips and examples on making Spring Data JPA code more robust by reducing reliance on hidden conventions and preferring explicit, testable query logic.
Spring Data JPA 最佳实践:事务与手写查询
了解如何避免 Spring 事务问题,并以不依赖 JPA 魔术的方式编写清晰的手写查询。

重點摘要

避免 Spring 事务配置的常见问题
用明确的手写查询替代不透明的 JPA 行为
采用实用建议提升可靠性与可维护性
本文由 Dmitry Protsenko 在 Level Up Coding 发布,聚焦 Spring Data JPA 的两项实务建议:正确处理事务和撰写不依赖 JPA 魔术的手写查询。文章指出,隐式的 JPA 行为或事务配置问题可能引发难以发现的缺陷,建议开发者使用明确的查询语句与清晰的事务边界,以提高代码的可预测性和可维护性。总体上主张以清晰、可测试的实现取代框架的隐式约定,从而在生产环境中减少意外和提高稳定性。
Spring Data JPA 最佳實務:交易與手寫查詢
了解如何避免 Spring 交易相關問題,並以不依賴 JPA 魔術的方式撰寫乾淨的手寫查詢。

重點摘要

避免 Spring 交易設定的常見陷阱
以明確的手寫查詢取代不透明的 JPA 行為
以實務建議提升穩定性與可維護性
此篇由 Dmitry Protsenko 在 Level Up Coding 發表的最佳實務文章,聚焦於 Spring Data JPA 的兩個實務面向:交易(Transaction)處理與不依賴 JPA 魔術的手寫查詢。文章提醒開發者,隱含的 JPA 行為或交易設定錯誤容易導致難以察覺的錯誤,建議採用清晰的查詢與明確的交易邊界,以提升可預測性與可維護性。整體主張以明確、可測試的實作取代隱晦的框架慣例,讓生產環境更可靠。

What is snapshotFlow in Jetpack Compose? Real Use Cases, Examples & Best Practices

What is snapshotFlow in Jetpack Compose? Real Use Cases, Examples & Best Practices
Learn how snapshotFlow turns Compose state changes into Kotlin Flows for side-effects, debounce, pagination, etc.

重點摘要

Converts Compose state reads into Kotlin Flow emissions
Useful for driving side-effects and collecting state changes outside composables
Commonly applied for debouncing input and powering pagination streams
snapshotFlow is a Jetpack Compose utility that converts observed Compose snapshot state reads into a Kotlin Flow, emitting values whenever that state changes. This bridge between Compose’s snapshot system and coroutines/Flow lets you collect and react to state changes outside of composable functions, making it easier to run side-effects, apply debounce logic, or feed paginated data pipelines. Because snapshotFlow emits based on snapshot read dependencies, it helps you capture only meaningful changes and combine Flow operators (for example debounce or distinctUntilChanged) to control emission frequency and downstream behavior. The referenced article outlines real use cases, example snippets, and best practices for integrating snapshotFlow into Compose apps so state-driven effects are lifecycle-aware, predictable, and easier to manage.
什么是 Jetpack Compose 的 snapshotFlow?真实用例、示例与最佳实践
了解 snapshotFlow 如何将 Compose 的状态变化转为 Kotlin Flow,用于副作用、去抖动、分页等场景。

重點摘要

把 Compose snapshot 状态读取转为 Kotlin Flow 发射
便于在 composable 外部收集状态并执行副作用
适用于输入去抖、分页及需控制发射频率的场景
snapshotFlow 是 Jetpack Compose 的一个工具,将对 Compose snapshot 状态的读取转换为 Kotlin Flow,当被观察的状态发生变化时会发出相应的值。它将 Compose 的状态系统与协程/Flow 连接起来,使得在 composable 之外收集状态变化并触发副作用变得更简单,便于实现去抖、分页等功能。由于 snapshotFlow 根据 snapshot 的读取依赖来决定何时发射,配合 Flow 操作符(如 debounce、distinctUntilChanged)可以有效控制事件发射频率与下游处理。文章介绍了真实用例、示例代码和最佳实践,幫助在 Compose 应用中更可预测且符合生命周期地管理状态驱动的效果。
什麼是 Jetpack Compose 的 snapshotFlow?實際應用、範例與最佳實務
了解 snapshotFlow 如何將 Compose 的狀態變更轉為 Kotlin Flow,以處理副作用、去抖動、分頁等需求。

重點摘要

將 Compose snapshot 狀態讀取轉成 Kotlin Flow 發射
便於在 composable 外部收集狀態並執行副作用
常用於輸入去抖、分頁或其他需控制發射頻率的場景
snapshotFlow 是 Jetpack Compose 中的工具,能把對 Compose snapshot 狀態的讀取轉換為 Kotlin Flow,當被觀察的狀態改變時就會發出值。透過這個橋接,可以在 composable 之外以 Flow 的方式收集狀態變化,方便執行副作用、實作去抖(debounce)或驅動分頁資料流。由於 snapshotFlow 根據 snapshot 的讀取依賴決定何時發射,搭配 Flow 的操作符(如 debounce、distinctUntilChanged)能有效控制事件頻率與下游處理。原文說明了實際應用案例、範例程式與最佳實務,協助在 Compose 應用中建立更可預期且符合生命週期的狀態到效果流程。

How I Built a Kotlin Compiler Plugin That Makes Everything Mockable

How I Built a Kotlin Compiler Plugin That Makes Everything Mockable
Kotlin classes and members are final by default, which prevents modern mocking libraries (like Mokkery) from mocking real production classes.

重點摘要

Kotlin's default final classes block mocking of production code.
The author built a compiler plugin to make classes and members mockable.
The plugin enables using existing mocking libraries with real production classes.
Many Kotlin users who adopt modern mocking libraries such as Mokkery face a recurring obstacle: Kotlin makes classes and members final by default, making it hard to mock real production classes. In this article Mohab Erabi explains the motivation and design behind a Kotlin compiler plugin he built to address that limitation. Instead of changing source APIs, the plugin modifies declarations at compile time so classes and members can be mocked by existing tools. The post outlines why the problem matters for testing, the high-level approach of using a compiler plugin to transform declarations, and the practical benefits of integrating that plugin into typical mocking workflows. It also discusses challenges encountered and the overall payoff for unit testing without altering production code.
我如何构建一个让所有东西都可被 Mock 的 Kotlin 编译器插件
Kotlin 默认将类和成员设为 final,导致像 Mokkery 这样的现代 mocking 工具无法对真实生产类进行 mock。

重點摘要

Kotlin 的默认 final 限制阻碍了对生产代码的 mock。
作者构建了一个编译器插件,在编译时使声明可被 mock。
该插件可与现有 mocking 工具整合,改善测试可行性。
作者指出,使用现代 mocking 工具(如 Mokkery)的开发者在对真实生产类进行 mock 时,会遇到 Kotlin 将类与成员默认设为 final 的问题,导致测试受限。为了解决该问题,他实现了一个 Kotlin 编译器插件,在编译阶段对声明进行转换,使类与成员在不改变源 API 的情况下可被 mock。文章介绍了该做法的动机、插件的设计思路与实现考量,以及与现有 mocking 流程的整合效果,并讨论了遇到的挑战与实践收益,从而在不修改生产代码的前提下提升单元测试的可行性与便利性。
我如何建構一個讓所有東西都可被 Mock 的 Kotlin 編譯器外掛
Kotlin 預設將類別與成員設為 final,導致像 Mokkery 這類現代 mocking 工具無法 mock 真實生產類別。

重點摘要

Kotlin 預設的 final 制約了對生產程式碼的 mock。
作者實作了一個編譯器外掛,在編譯時使宣告可被 mock。
外掛能與現有 mocking 工具整合,改善測試可行性。
作者指出,現代 mocking 工具(如 Mokkery)在對真實生產類別建模時,會遇到 Kotlin 預設將類別與成員設為 final 的限制,導致難以進行測試。為了解決這個痛點,他實作了一個 Kotlin 編譯器外掛,於編譯期間對宣告進行轉換,使類別與成員在不改變原始 API 的前提下可被 mock。文章說明了研究動機、外掛的設計與實作考量,以及整合現有 mocking 工具的效果,並分享了遇到的挑戰與實務收穫,讓開發者能在不修改生產程式碼的情況下,提升單元測試的可行性與便利性。

How I Fixed a Memory Leak in 2 Minutes (That Would Have Taken Hours with Android Studio Profiler)

How I Fixed a Memory Leak in 2 Minutes (That Would Have Taken Hours with Android Studio Profiler)
The author describes diagnosing and fixing a production memory leak in two minutes, a process that would have taken hours with Android Studio Profiler.

重點摘要

A production memory leak was identified
Resolved in two minutes using a faster approach
Significantly faster than using Android Studio Profiler
In this short Medium post, AndroidLeakTool recounts encountering a production memory leak and resolving it in two minutes by using a faster approach than the Android Studio Profiler. The piece contrasts the quick resolution with the much longer debugging time that would have been required had the profiler been used, and emphasizes the practical benefit of alternative diagnostic tools in production scenarios. While the article is brief, its core message is that choosing the right tooling and method can drastically reduce investigation time for real-world memory issues. Readers are given a concise account of the problem and outcome, with an implicit recommendation to consider specialized tools when tracing production leaks.
我如何在两分钟内修复内存泄漏(使用 Android Studio Profiler 要花数小时)
作者描述在生产环境定位并在两分钟内修复内存泄漏,而使用 Android Studio Profiler 则可能需要数小时。

重點摘要

发现生产环境的内存泄漏问题
用更快的方法两分钟内解决
远比 Android Studio Profiler 快
这篇由 AndroidLeakTool 在 Medium 发布的短文,讲述了作者在生产环境遇到内存泄漏并通过比 Android Studio Profiler 更迅速的方法在两分钟内修复的经历。文章通过对比强调了合适工具对排查生产问题的效率提升,说明在真实场景中选择专用或替代诊断工具可以显著缩短故障定位时间。内容虽简短,但传递出关键讯息:正确的工具和方法能够将耗时数小时的分析缩短为几分钟。
我如何在兩分鐘內修復記憶體洩漏(使用 Android Studio Profiler 要花好幾小時)
作者說明在生產環境遇到的記憶體洩漏,並以兩分鐘解決,若改用 Android Studio Profiler 則需耗費數小時。

重點摘要

發現生產環境的記憶體洩漏
使用更快的方法兩分鐘內解決
比 Android Studio Profiler 快得多
本文由 AndroidLeakTool 發表,簡述作者在生產環境遇到一個記憶體洩漏問題,並透過比 Android Studio Profiler 更快捷的方式在兩分鐘內修復。文章以對比手法突顯工具選擇的重要性,指出在真實環境中使用合適的診斷工具可大幅縮短排查時間。雖然內容精簡,但傳達了核心觀點:針對生產問題採用更有效的調試方法能節省大量時間,並暗示讀者在面對生產洩漏時考慮專用或替代工具。

Menguasai Layout Jetpack Compose: Panduan Lengkap untuk Pemula

Mastering Jetpack Compose Layouts: A Complete Beginner's Guide
If you've just moved from XML to Jetpack Compose, welcome to the future of Android development!

重點摘要

Introduces Compose as the modern alternative to XML for Android UI
Explains core layout primitives, modifiers, alignment and measurement
Offers practical examples, migration tips and best practices for beginners
This article is a comprehensive beginner's guide to mastering layouts in Jetpack Compose, aimed at developers transitioning from XML-based UIs. It frames Compose as the modern approach for Android interface development and walks readers through essential layout primitives (such as Row, Column, and Box), the role of Modifiers, alignment and measurement concepts, and how these pieces interact to build responsive layouts. The guide emphasizes practical, step-by-step examples and migration advice to help developers convert existing XML layouts into Compose equivalents while improving maintainability and performance. It also highlights common pitfalls and best practices for arranging composables effectively, enabling readers to adopt Compose confidently and design flexible, idiomatic UI components.
精通 Jetpack Compose 布局:初学者完整指南
如果你刚从 XML 转向 Jetpack Compose,欢迎进入 Android 开发的未来!

重點摘要

介绍 Compose 作为替代 XML 的现代 Android UI 方案
讲解 Row、Column、Box 等核心布局组件及 Modifier、对齐与测量概念
提供实作示例、从 XML 迁移建议与布局最佳实践
本文为初学者提供一份完整的 Jetpack Compose 布局指南,面向从 XML 迁移到 Compose 的开发者,解释其优势与基本理念。文章介绍关键布局组件(如 Row、Column、Box)、Modifier 的使用、对齐和测量的核心概念,并说明这些要素如何协同构建响应式界面。通过逐步示例和迁移建议,示范如何将现有 XML 布局转为 Compose 实现,并提出常见问题与优化技巧,帮助读者快速掌握 Compose,创建可维护且灵活的 UI 组件。
精通 Jetpack Compose 佈局:新手完整指南
如果你剛從 XML 轉向 Jetpack Compose,歡迎進入 Android 開發的未來!

重點摘要

介紹 Compose 作為取代 XML 的現代 Android UI 方法
說明 Row、Column、Box 等核心佈局元件與 Modifier、對齊與測量概念
提供實作範例、從 XML 遷移的建議與佈局最佳實務
本文為初學者提供一份完整的 Jetpack Compose 佈局指南,針對從 XML 轉移至 Compose 的開發者說明背景與優勢。內容介紹主要佈局元件(如 Row、Column、Box)、Modifier 的用途、對齊與測量的基本概念,並說明這些要素如何協同構成響應式介面。文章以步驟化範例與遷移建議為核心,示範如何將既有 XML 佈局轉換為 Compose 實作,同時提出常見陷阱與優化技巧,幫助讀者快速上手並建立可維護且具彈性的 Compose UI。

Stop Memorizing ‘in' and ‘out': Use This Simple Mental Model for Kotlin Variance

Stop Memorizing 'in' and 'out': Use This Simple Mental Model for Kotlin Variance
Stop memorizing 'in' and 'out' — learn Kotlin variance with one simple mental model, supported by real examples, diagrams, and an interview-ready cheat sheet.

重點摘要

Replace rote memorization of 'in'/'out' with a single mental model.
Uses real code examples and diagrams to clarify variance.
Provides an interview-ready cheat sheet for quick recall.
This article argues against memorizing Kotlin's 'in' and 'out' keywords in isolation and instead presents a single, simple mental model to reason about variance. It explains the concept using concrete examples and diagrams so readers can see how types behave in practice, and it packages the key points into an interview-ready cheat sheet for quick review. The goal is to make variance intuitive and actionable, reducing reliance on rules to be memorized and increasing understanding through visualization and hands-on examples. The piece is aimed at developers preparing for interviews or seeking a clearer, more durable grasp of Kotlin's type variance.
别再死记 in 与 out:用这个简单心智模型理解 Kotlin 的变异性
别再死记 in 与 out;用一个简单心智模型配合实例、图示和面试速查表来学习 Kotlin 的变异性。

重點摘要

以单一心智模型代替对 in/out 的死记。
通过实例与图示说明变异性的实际表现。
包含面试用的速查表,便于快速复习要点。
文章主张不再机械记忆 Kotlin 的 in 与 out,而是采用一个简单且一致的心智模型来理解变异性。作者通过真实代码示例与示意图展示类型在不同场景下的行为,并整理出一份面试级的速查表,方便快速回顾和实战应用。核心目的在于用直观和可操作的方式,让开发者把抽象的类型变异性转化为容易理解且可在面试或日常编码中运用的知识。
別再死記 in 與 out:用這個簡單心智模型理解 Kotlin 的變異性
別再死記 in 與 out;用一個簡單心智模型搭配實例、圖示和面試速查表來學習 Kotlin 的變異性。

重點摘要

用單一心智模型取代對 in/out 的死記硬背。
以實例與圖示展示變異性的實際行為。
提供面試速查表,方便快速複習重點。
本文主張不要單純記住 Kotlin 的 in 與 out 關鍵字,而是透過一個簡單且直觀的心智模型來理解變異性。作者以實際程式範例與示意圖說明型別如何在不同情境下表現,並整理出一張面試用的速查表,方便在準備面試或快速回顧時使用。重點在於透過視覺化與操作性的示例,讓原本抽象的型別變異性變得可理解且易於應用,而非依賴記憶規則。

Implementing Android 12 Splash Screen API with Animated Vector Drawable (AVD)

Implementing Android 12 Splash Screen API with Animated Vector Drawable (AVD)
I want to write about my learning experience implementing Android 12 Splash Screen API; honestly, this update makes things easier.

重點摘要

Author shares a personal learning experience implementing Android 12 Splash Screen API
Focus on integrating Animated Vector Drawable (AVD) with the new API
Author notes the Android 12 update simplifies the splash screen workflow
Naufal Fajar Imani presents a personal account of learning to implement Android 12's Splash Screen API, with particular attention to using Animated Vector Drawable (AVD). The post is framed as the author's learning experience rather than a formal tutorial, and it emphasizes that the Android 12 update makes handling splash screens easier for developers. The author signals an intention to describe how he approached implementation and to share his impressions of the API change and AVD's role in that process. Readers are directed to the Medium article for the full write-up and any detailed examples or practical notes the author provides.
在 Android 12 使用 Animated Vector Drawable (AVD) 实现 Splash Screen API
我想写一下我实现 Android 12 Splash Screen API 的学习经验;说实话,这次更新让事情变得更容易。

重點摘要

作者分享实现 Android 12 Splash Screen API 的学习过程
重点关注将 Animated Vector Drawable(AVD)与新 API 结合
作者指出 Android 12 的更新使启动屏实现更为简便
作者 Naufal Fajar Imani 在 Medium 上以个人视角记录他实现 Android 12 Splash Screen API 的学习经验,并在标题中提到使用 Animated Vector Drawable(AVD)。文章强调 Android 12 的更新让处理启动屏的流程更简单,内容以作者的实践感受和观察为主,而非标准教程。想了解完整实现细节或作者的示例与步骤,请继续阅读原文以获得完整说明。
在 Android 12 使用 Animated Vector Drawable (AVD) 實作 Splash Screen API
我想分享我實作 Android 12 Splash Screen API 的學習經驗;說實話,這次更新讓事情變得更簡單。

重點摘要

作者分享實作 Android 12 Splash Screen API 的學習經驗
文章聚焦於將 Animated Vector Drawable (AVD) 與新 API 結合
作者指出 Android 12 的更新使啟動畫面處理變得較為簡便
作者 Naufal Fajar Imani 在 Medium 上以第一人稱敘述他實作 Android 12 Splash Screen API 的學習經歷,標題同時表明他關注 Animated Vector Drawable(AVD)的應用。文中強調這次 Android 12 的更新讓處理啟動畫面更加簡便,並說明文章以個人經驗和觀察為主,而非正式教學。讀者若欲取得完整細節或作者實作的具體內容,可參考原文以獲得完整說明與範例。

Android’s Mobile Device Management (MDM): Your Little Customized Government

Android’s Mobile Device Management (MDM): Your Little Customized Government
Most companies — including the author's — are taking security standards more seriously, and Android MDM functions as a customizable authority over devices.

重點摘要

Companies are increasingly adopting Android MDM to meet security standards.
MDM gives organizations granular control over device settings, apps, and policies.
The centralized control of MDM raises trade-offs between security, privacy, and user autonomy.
The piece describes how many companies, including the author’s, have become more serious about complying with security standards and are turning to Android Mobile Device Management (MDM) as a tool to enforce those policies. Framed as a “little customized government,” Android MDM lets organizations configure devices, push policies, manage apps, and take remote actions to protect corporate data. While MDM helps standardize and strengthen security across fleets of devices, it also centralizes control over users’ phones and tablets, creating tensions around privacy, personal use, and employee autonomy. The article highlights the practical benefits of MDM for compliance and risk reduction while urging awareness of the implications of giving employers deep management capabilities over mobile endpoints.
Android 移动设备管理(MDM):你的小型定制政府
包括作者在内的大多数公司正越来越重视安全标准,而 Android MDM 就像可定制的设备管理当局。

重點摘要

企业逐步采用 Android MDM 以满足安全合规要求。
MDM 允许组织对设备设置、应用和策略进行精细控制。
集中管理在提升安全性的同时,也引发隐私与自主性的权衡。
文章指出,包括作者所在公司在内的许多企业为遵循安全标准,正越来越多地采用 Android 的移动设备管理(MDM)。作者将 MDM 比喻为“小型定制政府”,说明它能够帮助企业配置设备、下发策略、管理应用并执行远程操作以保护公司数据。MDM 在提升合规性和降低风险方面有明显优势,但也使企业掌握大量设备控制权,从而带来对员工隐私与个人使用自由的影响。文章提醒在强化安全与合规的同时,应权衡对用户自主性和隐私的影响。
Android 行動裝置管理(MDM):你的小型客製化政府
包括作者在內的多數公司都愈來愈重視資安標準,而 Android MDM 就像能客製化的裝置管理當局。

重點摘要

企業日益採用 Android MDM 以符合資安規範。
MDM 可讓組織細部控管裝置設定、應用與政策。
集中式管理在提升安全性的同時,也帶來隱私與自主性的權衡。
文章指出,包括作者在內的許多公司為了遵循資安標準,開始更廣泛地使用 Android 的行動裝置管理(MDM)。作者以「小型客製化政府」形容 MDM,強調它能協助企業設定裝置、強制政策、部署應用並進行遠端管理來保護公司資料。MDM 在統一管理與降低風險方面效果顯著,但同時把大量控制權集中在企業手中,可能影響員工的隱私與個人使用空間。作者提醒在追求合規與安全的同時,也應考量對使用者自主性與隱私的影響。

Generated by Kotlin News Summarizer with AI Summaries