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

Bài đăng

Hiển thị các bài đăng có nhãn Dart

Genkit Dart: app AI full-stack không rời Dart

Genkit Dart là framework mã nguồn mở cho app AI với API model-agnostic (Google, Anthropic, OpenAI…). Chạy được cả server lẫn bên trong client Flutter — một ngôn ngữ từ prototype tới production. Ý tưởng lõi Genkit() + plugin provider. Structured output type-safe và tool calling. Hội thoại nhiều lượt và observability sẵn có. import 'package:genkit/genkit.dart' ; import 'package:genkit_google_genai/genkit_google_genai.dart' ; void main () async { final ai = Genkit (plugins : [ googleAI ()]); final response = await ai. generate ( model : googleAI. gemini ( 'gemini-flash-latest' ), prompt : 'Vì sao Dart hợp với ứng dụng AI?' , ); print (response.text); } Ghép vào sản phẩm Flutter Tầng Lựa chọn UI nhạy latency Genkit client / Firebase AI Logic Tool, RAG, billing, audit Genkit server Contract chung Model Dart sinh một lần Cạm bẫy Ship prompt server khổng lồ trong bundle app. Trộn SDK pro...

Genkit Dart: full-stack AI apps without leaving Dart

Genkit Dart is an open-source framework for AI-powered apps with a model-agnostic API (Google, Anthropic, OpenAI, …). It runs server-side or inside Flutter clients, so one language covers prototype to production. Core ideas Genkit() + plugins for providers. Type-safe structured output and tool calling. Multi-turn conversations and built-in observability. import 'package:genkit/genkit.dart' ; import 'package:genkit_google_genai/genkit_google_genai.dart' ; void main () async { final ai = Genkit (plugins : [ googleAI ()]); final response = await ai. generate ( model : googleAI. gemini ( 'gemini-flash-latest' ), prompt : 'Why is Dart a great language for AI applications?' , ); print (response.text); } How it fits a Flutter product Layer Choice Latency-sensitive UI polish Client Genkit / Firebase AI Logic Tools, RAG, billing, audit Server Genkit Shared contracts Dart models generated once...

Tiêm phụ thuộc trong Flutter mà không cần nghi thức rườm rà

Tiêm phụ thuộc có một cái tên đáng sợ cho một ý tưởng hết sức bình thường: một lớp nên được trao thứ nó cần thay vì tự dựng hoặc tự đi tìm. Toàn bộ khái niệm chỉ có vậy. Mọi thứ còn lại — container, locator, provider, mã sinh tự động — chỉ là bộ máy để giao hàng. Lý do đáng quan tâm là kiểm thử. Viết ApiClient() bên trong một repository nghĩa là mọi test của repository đó đều gọi mạng thật. Truyền ApiClient vào nghĩa là mọi test đều truyền được bản giả. Đó là toàn bộ phần thưởng, và thế là đủ. Tiêm qua constructor, không cần gói nào final class UserRepository { const UserRepository ( this ._api, this ._cache); final ApiClient _api; final UserCache _cache; Future < User > fetch ( String id) async { final cached = _cache. get (id); if (cached != null ) return cached; final user = await _api. getUser (id); _cache. put (user); return user; } } Kiểm thử nó không cần framework nào: test ( 'trả về user từ cache mà...

Dependency injection in Flutter without the ceremony

Dependency injection has an intimidating name for an unremarkable idea: a class should be handed what it needs rather than constructing or locating it. That is the whole concept. Everything else — containers, locators, providers, generated code — is machinery for delivering it. The reason to care is testing. ApiClient() written inside a repository means every test of that repository makes real network calls. ApiClient passed in means every test can pass a fake. That is the entire payoff, and it is enough. Constructor injection, which needs no package final class UserRepository { const UserRepository ( this ._api, this ._cache); final ApiClient _api; final UserCache _cache; Future < User > fetch ( String id) async { final cached = _cache. get (id); if (cached != null ) return cached; final user = await _api. getUser (id); _cache. put (user); return user; } } Testing this requires no framework at all: test ( ...

Agent Skills cho Dart và Flutter: workflow agent rẻ và chuẩn hơn

Agent giỏi gõ phím nhưng kém gu. Agent Skills mã hóa gu Flutter/Dart thành hướng dẫn ngắn theo task mà agent load được: cách thêm integration test, setup localization, cấu trúc feature. Vì sao skill thắng system prompt khổng lồ Theo scope. Chỉ load việc đang cần. Version cùng hệ sinh thái. Skill ship kèm package và docs. Rẻ token. Mặt phẳng tool MCP cũng được gộp để agent dành budget cho code của bạn. Dùng hàng ngày Cài/cấu hình Dart & Flutter MCP server cho agent (Claude Code, Gemini CLI, Cursor…). Ưu tiên invoke skill chính thức hơn prompt tự do “viết màn login”. Giữ skill local cho luật nhà (folder layout, convention Riverpod, style test). Package skills Pub package có thể ship skill riêng để agent biết idioms của package đó , không phải Flutter chung chung. Nếu bạn maintain plugin phổ biến, skill đang thành một phần DX tốt — và giảm API bị bịa. Anti-pattern Một prompt vừa redesign kiến trúc, vừa add feature, vừa viết test. Hãy tách. Tắt skill để “tiết kiệ...

Dart and Flutter Agent Skills: cheaper, better agent workflows

Agents are good at typing and bad at taste. Agent Skills encode Flutter/Dart taste as short, task-oriented instructions your agent can load: how to add integration tests, how to set up localization, how to structure a feature. Why skills beat a giant system prompt Scoped. Load only what the task needs. Versioned with the ecosystem. Skills ship alongside packages and docs. Token-cheap. The MCP tool surface was also consolidated so the agent spends budget on your code, not on boilerplate tool schemas. How to use them day to day Install/configure the Dart & Flutter MCP server for your agent (Claude Code, Gemini CLI, Cursor, etc.). Prefer invoking an official skill over free-form “write me a login screen.” Keep project-local skills for house rules (folder layout, Riverpod conventions, test style). Package skills Pub packages can ship their own skills so an agent knows this package’s idioms, not generic Flutter. If you maintain a popular plugin, a skill is becoming p...

Serverpod: full-stack Dart phía sau Flutter

Serverpod là backend “không, bạn không cần học ba ngôn ngữ”: server Dart, client Flutter sinh tự động, tooling database kèm theo. Vì sao team chọn Type dùng chung hết lệch JSON. Auth và scaffolding database giảm lo trang trắng. Một toolchain cho hiring và CI. Cạm bẫy Lock-in full-stack là thật — giữ domain logic di động nếu có thể tách sau. Không để secret trong path code client sinh. Cân nhắc Serverpod khi team Flutter-first và muốn backend mạch lạc không đổi ngữ cảnh Node/Go. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Jaspr: Dart server-driven cho web

Jaspr mang mental model component lên Dart phía server. Nếu bạn thích cấu trúc Flutter nhưng cần HTML/SEO, đây là hệ sinh thái kề cận — đáng chú ý khi góp phần vào hiện diện web của chính Flutter. Bài học Model Dart dùng chung giữa API, UI server và client Flutter giảm lệch DTO. SSR/hydration là vấn đề đóng gói nhiều như vấn đề UI. Server component khuyến khích trang nhàm chán, cache được. Cạm bẫy Đừng giả định widget Flutter chạy nguyên xi. Constraint layout và lifecycle khác mobile. Cân nhắc Jaspr cho site nội dung và dashboard nơi SEO quan trọng và Dart đã là ngôn ngữ của bạn. Bài viết gốc đăng tại FlutterCook . Bản trên đó là bản được cập nhật mới nhất.

Genkit Dart: app AI full-stack không rời Dart

Genkit Dart là framework mã nguồn mở cho app AI với API model-agnostic (Google, Anthropic, OpenAI…). Chạy được cả server lẫn bên trong client Flutter — một ngôn ngữ từ prototype tới production. Ý tưởng lõi Genkit() + plugin provider. Structured output type-safe và tool calling. Hội thoại nhiều lượt và observability sẵn có. import 'package:genkit/genkit.dart' ; import 'package:genkit_google_genai/genkit_google_genai.dart' ; void main () async { final ai = Genkit (plugins : [ googleAI ()]); final response = await ai. generate ( model : googleAI. gemini ( 'gemini-flash-latest' ), prompt : 'Vì sao Dart hợp với ứng dụng AI?' , ); print (response.text); } Ghép vào sản phẩm Flutter Tầng Lựa chọn UI nhạy latency Genkit client / Firebase AI Logic Tool, RAG, billing, audit Genkit server Contract chung Model Dart sinh một lần Cạm bẫy Ship prompt server khổng lồ trong bundle app. Trộn SDK pro...

Agent Skills cho Dart và Flutter: workflow agent rẻ và chuẩn hơn

Agent giỏi gõ phím nhưng kém gu. Agent Skills mã hóa gu Flutter/Dart thành hướng dẫn ngắn theo task mà agent load được: cách thêm integration test, setup localization, cấu trúc feature. Vì sao skill thắng system prompt khổng lồ Theo scope. Chỉ load việc đang cần. Version cùng hệ sinh thái. Skill ship kèm package và docs. Rẻ token. Mặt phẳng tool MCP cũng được gộp để agent dành budget cho code của bạn. Dùng hàng ngày Cài/cấu hình Dart & Flutter MCP server cho agent (Claude Code, Gemini CLI, Cursor…). Ưu tiên invoke skill chính thức hơn prompt tự do “viết màn login”. Giữ skill local cho luật nhà (folder layout, convention Riverpod, style test). Package skills Pub package có thể ship skill riêng để agent biết idioms của package đó , không phải Flutter chung chung. Nếu bạn maintain plugin phổ biến, skill đang thành một phần DX tốt — và giảm API bị bịa. Anti-pattern Một prompt vừa redesign kiến trúc, vừa add feature, vừa viết test. Hãy tách. Tắt skill để “tiết kiệ...

Serverpod: full-stack Dart behind Flutter

Serverpod is the “no, you may not learn three languages” backend: Dart server, generated Flutter clients, database tooling included. Why teams pick it Shared types end JSON drift. Auth and database scaffolding reduce blank-page anxiety. One toolchain for hiring and CI. Pitfalls Full-stack lock-in is real — keep domain logic portable if you might split later. Do not put secrets in client-generated code paths. Consider Serverpod when the team is Flutter-first and wants a coherent backend without Node/Go context switching. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

Jaspr: server-driven Dart for the web

Jaspr brings a component mental model to Dart on the server. If you like Flutter’s structure but need HTML/SEO, this is the adjacent ecosystem — notably powering parts of Flutter’s own web presence. Lessons Shared Dart models between API, server UI, and Flutter clients reduce DTO drift. SSR/hydration is a packaging problem as much as a UI problem. Server components encourage boring, cacheable pages. Pitfalls Do not assume Flutter widgets work unchanged. Layout constraints and lifecycle differ from mobile. Consider Jaspr for content sites and dashboards where SEO matters and Dart is already your language. Originally published on FlutterCook . Read the latest version there — that copy is the one kept up to date.

Genkit Dart: full-stack AI apps without leaving Dart

Genkit Dart is an open-source framework for AI-powered apps with a model-agnostic API (Google, Anthropic, OpenAI, …). It runs server-side or inside Flutter clients, so one language covers prototype to production. Core ideas Genkit() + plugins for providers. Type-safe structured output and tool calling. Multi-turn conversations and built-in observability. import 'package:genkit/genkit.dart' ; import 'package:genkit_google_genai/genkit_google_genai.dart' ; void main () async { final ai = Genkit (plugins : [ googleAI ()]); final response = await ai. generate ( model : googleAI. gemini ( 'gemini-flash-latest' ), prompt : 'Why is Dart a great language for AI applications?' , ); print (response.text); } How it fits a Flutter product Layer Choice Latency-sensitive UI polish Client Genkit / Firebase AI Logic Tools, RAG, billing, audit Server Genkit Shared contracts Dart models generated once...

Dart and Flutter Agent Skills: cheaper, better agent workflows

Agents are good at typing and bad at taste. Agent Skills encode Flutter/Dart taste as short, task-oriented instructions your agent can load: how to add integration tests, how to set up localization, how to structure a feature. Why skills beat a giant system prompt Scoped. Load only what the task needs. Versioned with the ecosystem. Skills ship alongside packages and docs. Token-cheap. The MCP tool surface was also consolidated so the agent spends budget on your code, not on boilerplate tool schemas. How to use them day to day Install/configure the Dart & Flutter MCP server for your agent (Claude Code, Gemini CLI, Cursor, etc.). Prefer invoking an official skill over free-form “write me a login screen.” Keep project-local skills for house rules (folder layout, Riverpod conventions, test style). Package skills Pub packages can ship their own skills so an agent knows this package’s idioms, not generic Flutter. If you maintain a popular plugin, a skill is becoming p...

Stream trong Dart chuyên sâu: backpressure, broadcast và những rò rỉ ở giữa

Bad state: Stream has already been listened to. là lỗi đẩy phần lớn mọi người lên Stack Overflow, và câu trả lời họ tìm thấy — “dùng .asBroadcastStream() ” — thường là cách sửa sai. Nó làm lỗi biến mất và âm thầm thay đổi ngữ nghĩa phân phối dữ liệu của bạn. Hai loại stream, và vì sao mặc định là loại nghiêm ngặt Stream đơn đăng ký chỉ được nghe đúng một lần. Nó đệm sự kiện cho tới khi có listener, và giao mọi sự kiện cho listener đó. Đọc file, thân phản hồi HTTP và các hàm async* đều sinh ra loại này. Stream broadcast có bao nhiêu listener cũng được, chỉ giao sự kiện cho những listener đang đăng ký, và không đệm gì cả. Listener tới muộn thì đơn giản là lỡ mất những gì đã qua. final single = StreamController < int >(); // đơn đăng ký final bus = StreamController < int >. broadcast (); Cụm “không đệm gì cả” là mấu chốt. Chuyển một stream đơn đăng ký sang broadcast để làm im lỗi nghĩa là các sự kiện phát ra trước khi listener thứ hai gắn vào sẽ mất — kh...

Record và pattern trong Dart: chúng thay thế những gì

Trước khi có record, trả về hai giá trị từ một hàm nghĩa là chọn một trong ba lựa chọn đều không hấp dẫn: một class chỉ dùng một lần, một List<Object> mà bạn phải truy cập theo chỉ số, hoặc hai tham số ra thông qua một lớp bọc. Record biến nó thành một dòng. ({ int width, int height}) measure ( String text) { // ... return (width : 120 , height : 40 ); } final size = measure ( 'hello' ); print (size.width); Đó là tính năng nổi bật nhất, và nó là phần nhỏ nhất trong những gì record cùng pattern đã thay đổi. Record: theo cấu trúc, không theo tên Kiểu của một record chính là hình dạng của nó. (int, String) và (int, String) là cùng một kiểu bất kể chúng được tạo ở đâu, và đó là điểm phân biệt record với class. // Theo vị trí ( String , int ) parseEntry ( String line) { final parts = line. split ( ':' ); return (parts[ 0 ], int . parse (parts[ 1 ])); } // Có tên — rõ ràng hơn ở nơi gọi ({ String name, int score}) parseNamed ( ...