Chuyển đến nội dung chính

Bài đăng

Switch expressions for cleaner Flutter mapping — hướng dẫn Flutter

Switch expressions make state-to-UI mapping readable and exhaustive. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Mapping enums and states to widgets without arrow soup. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Pair with sealed classes for compile-time exhaustiveness. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure ...
Các bài đăng gần đây

Swift Package Manager plugin migration checklist for Flutter — hướng dẫn Flutter

CocoaPods is maintenance mode. Flutter 3.44+ resolves iOS/macOS deps with SwiftPM by default. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi What iOS/macOS plugin authors must ship after SwiftPM became the default. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Unmigrated plugins score lower on pub.dev and will eventually stop resolving. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate inten...

Swift Package Manager là mặc định iOS/macOS — rời CocoaPods

CocoaPods đang ở chế độ maintenance. Flutter 3.44 đặt Swift Package Manager làm mặc định cho dependency iOS và macOS. CLI migrate Xcode project ở lần flutter run / flutter build kế tiếp. App developer thấy gì Happy path không cần cài Ruby/CocoaPods. Add-to-App có flutter build swift-package để đóng gói module thành Swift Package. Plugin còn bắt buộc CocoaPods sẽ bị CLI cảnh báo và fallback tạm. Plugin author cần ship gì Thêm Package.swift . Depend FlutterFramework nếu đã migrate pilot 2024. Nâng constraint Flutter tối thiểu lên 3.44 khi chuyển. Plugin chưa migrate bị trừ điểm pub.dev và sẽ không resolve được nữa. Opt-out tạm # pubspec.yaml flutter : enable-swift-package-manager : false Hoặc --no-enable-swift-package-manager trên CLI. Opt-out sẽ bị gỡ; mở issue kèm Xcode project nếu SwiftPM làm hỏng tích hợp thật. Checklist trước khi xóa Podfile flutter clean rồi build iOS đầy đủ CI không còn cài CocoaPods cho app này Mọi plugin trong tree resolve bằ...

Switch expressions for cleaner Flutter mapping

Switch expressions make state-to-UI mapping readable and exhaustive. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Mapping enums and states to widgets without arrow soup. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Pair with sealed classes for compile-time exhaustiveness. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates th...

Swift Package Manager plugin migration checklist for Flutter

CocoaPods is maintenance mode. Flutter 3.44+ resolves iOS/macOS deps with SwiftPM by default. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence What iOS/macOS plugin authors must ship after SwiftPM became the default. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Unmigrated plugins score lower on pub.dev and will eventually stop resolving. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, su...

Swift Package Manager is the iOS/macOS default — leave CocoaPods behind

CocoaPods is in maintenance mode. Flutter 3.44 makes Swift Package Manager the default for iOS and macOS dependency resolution. The CLI migrates the Xcode project on the next flutter run / flutter build . What app developers see No Ruby/CocoaPods install required for the happy path. Add-to-App gains flutter build swift-package to emit a Swift Package for native hosts. Plugins that still require CocoaPods trigger a CLI warning and temporary fallback. What plugin authors must ship If you maintain an iOS/macOS plugin: Add a Package.swift . Depend on FlutterFramework if you migrated in the 2024 pilot. Raise the minimum Flutter constraint to 3.44 when you switch. Unmigrated plugins score lower on pub.dev and will eventually stop resolving. Temporary opt-out # pubspec.yaml flutter : # temporary escape hatch — file a bug if you need it enable-swift-package-manager : false Or pass --no-enable-swift-package-manager on the command line. Opt-outs will be removed; op...

Stylus pressure and tilt input in Flutter — hướng dẫn Flutter

Creative and note apps live on pen latency and pressure. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Apple Pencil, S-Pen, and Windows pen APIs. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Windows/Linux support is improving via community contributions. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả ...

Structured output and tool calling in Flutter AI apps — hướng dẫn Flutter

UIs need typed answers. Structured output beats regex on markdown. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi JSON schema, validation, and UI for tool confirmation. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Confirm dangerous tools with explicit user consent UI. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiể...

Streaming LLM responses into Flutter UIs token by token — hướng dẫn Flutter

Streaming feels faster even at the same total latency. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Partial JSON, interruptibility, and scroll locking. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Users must be able to stop generation mid-stream. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả string ...

Stylus pressure and tilt input in Flutter

Creative and note apps live on pen latency and pressure. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Apple Pencil, S-Pen, and Windows pen APIs. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Windows/Linux support is improving via community contributions. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls ...

Structured output and tool calling in Flutter AI apps

UIs need typed answers. Structured output beats regex on markdown. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence JSON schema, validation, and UI for tool confirmation. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Confirm dangerous tools with explicit user consent UI. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the inte...

Streaming LLM responses into Flutter UIs token by token

Streaming feels faster even at the same total latency. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Partial JSON, interruptibility, and scroll locking. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Users must be able to stop generation mid-stream. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the bou...

Replying to store reviews without sounding like a bot — hướng dẫn Flutter

Reviews are public product support. Treat them that way. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Tone, escalation paths, and version-specific answers. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Reply with a version number and a next step. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả string c...

SKStoreReview and in-app review prompts that do not annoy — hướng dẫn Flutter

Review prompts amplify product sentiment — good and bad. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Timing, frequency caps, and happy-path triggers. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Trigger after a success moment, never on first launch. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả str...

Mapping App Store guidelines to common Flutter features — hướng dẫn Flutter

Most rejections map to a handful of guideline sections. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi UGC, payments, health, and kids categories. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Build moderation and account deletion before UGC launch. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về data có kiểu hoặc failure có kiểu, không trả string ...

Replying to store reviews without sounding like a bot

Reviews are public product support. Treat them that way. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Tone, escalation paths, and version-specific answers. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Reply with a version number and a next step. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the boun...

SKStoreReview and in-app review prompts that do not annoy

Review prompts amplify product sentiment — good and bad. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Timing, frequency caps, and happy-path triggers. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Trigger after a success moment, never on first launch. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the...

Mapping App Store guidelines to common Flutter features

Most rejections map to a handful of guideline sections. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence UGC, payments, health, and kids categories. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Build moderation and account deletion before UGC launch. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as load, submit, refresh, or retry. A controller or use case validates the intent and calls the bou...