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

Bài đăng

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

Window management APIs for Flutter desktop apps — hướng dẫn Flutter

Desktop apps are multi-surface. Window APIs are catching up with Canonical. 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 Multi-window state, focus fixes, and native handle access. 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ế Persist window size/position yourself — the framework will not. 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...

Product flavors on Windows and Linux for CI matrices — hướng dẫn Flutter

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. 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 Per-flavor assets and —flavor builds join Android/iOS on desktop. 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ế CI can produce side-by-side installers with different IDs and icons. 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...

Window management APIs for Flutter desktop apps

Desktop apps are multi-surface. Window APIs are catching up with Canonical. 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 Multi-window state, focus fixes, and native handle access. 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 Persist window size/position yourself — the framework will not. 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 c...

Product flavors on Windows and Linux for CI matrices

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. 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 Per-flavor assets and —flavor builds join Android/iOS on desktop. 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 CI can produce side-by-side installers with different IDs and icons. 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 ...

Desktop multi-window: popups, dialogs, and windowHandle — hướng dẫn Flutter

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. 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 Experimental windowing APIs accelerate with Canonical as desktop steward. 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ế Keep the primary workflow single-window until APIs graduate. 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 bou...

desktop_multi_window: isolate desktop surfaces intentionally

desktop_multi_window: isolate desktop surfaces intentionally desktop_multi_window is useful because it focuses on window lifecycle, arguments, isolate boundaries, and platform constraints. The important engineering move is to place the package behind a clear boundary, so your Flutter UI depends on a stable capability rather than a vendor-shaped API. What the library should own Keep package calls inside a named adapter or feature boundary. Make lifecycle, errors, and loading state part of a testable contract. Expose only the capability the app needs; hide implementation details from the whole tree. A focused starting point final window = await WindowController . create ( WindowConfiguration (arguments : jsonEncode ({ 'route' : '/settings' })), ); await window. show (); await window. setTitle ( 'Settings' ); Production checklist Read the README and changelog for the exact version you pin. Add one test for lifecycle, failure, and app bac...

Impeller on desktop: SDF text and Metal/Vulkan defaults — hướng dẫn Flutter

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. 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 Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. 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ế Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. 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 ...

Flutter trên desktop: cửa sổ giờ là một phần của ứng dụng bạn

Một ứng dụng Flutter chạy được trên desktop và một ứng dụng Flutter thuộc về desktop là hai phần mềm khác nhau. Cái thứ nhất là bố cục điện thoại kéo giãn ra 1920 pixel. Cái thứ hai biết cửa sổ của mình có thể bị co lại tới mức phi lý, biết người dùng mong Cmd+W đóng một tab, biết chuột phải phải bật menu ngữ cảnh, và biết cuộn bằng trackpad không phải cùng một cử chỉ với kéo bằng ngón tay. Chẳng có gì trong số này là khó. Nó chỉ là danh sách những thứ mà di động chưa bao giờ bắt bạn nghĩ tới. Cửa sổ có vòng đời do bạn điều khiển Future < void > main () async { WidgetsFlutterBinding . ensureInitialized (); await windowManager. ensureInitialized (); const options = WindowOptions ( size : Size ( 1200 , 800 ), minimumSize : Size ( 720 , 480 ), center : true , titleBarStyle : TitleBarStyle .normal, ); await windowManager. waitUntilReadyToShow (options, () async { await windowManager. show (); await windowManager. focus ()...

Desktop multi-window: popups, dialogs, and windowHandle

Context menus and tool palettes need more than one surface. Windowing APIs are how you get there. 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 Experimental windowing APIs accelerate with Canonical as desktop steward. 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 Keep the primary workflow single-window until APIs graduate. 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...

Window management APIs for Flutter desktop apps — hướng dẫn Flutter

Desktop apps are multi-surface. Window APIs are catching up with Canonical. 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 Multi-window state, focus fixes, and native handle access. 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ế Persist window size/position yourself — the framework will not. 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...

Product flavors on Windows and Linux for CI matrices — hướng dẫn Flutter

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. 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 Per-flavor assets and —flavor builds join Android/iOS on desktop. 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ế CI can produce side-by-side installers with different IDs and icons. 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...

Impeller on desktop: SDF text and Metal/Vulkan defaults

Desktop Impeller defaults land with Signed Distance Function text and Wide Gamut on macOS. 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 Flutter 3.47 makes Impeller the default desktop renderer — what changes for text and jank. 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 Shader compilation jank dies; SDF glyphs stay sharp on lower-density desktop displays. 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 ...

Window management APIs for Flutter desktop apps

Desktop apps are multi-surface. Window APIs are catching up with Canonical. 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 Multi-window state, focus fixes, and native handle access. 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 Persist window size/position yourself — the framework will not. 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 c...

Product flavors on Windows and Linux for CI matrices

Dev/staging/prod builds are no longer mobile-only. 3.47 brings flavors to Windows and Linux. 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 Per-flavor assets and —flavor builds join Android/iOS on desktop. 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 CI can produce side-by-side installers with different IDs and icons. 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 ...

Impeller thành renderer desktop mặc định — thực sự đổi gì

Impeller mặc định trên mobile đã có từ trước. Flutter 3.47 hoàn tất trên macOS, Windows và Linux . App desktop giờ nhắm Metal (macOS) và Vulkan (Windows/Linux) với tập shader cố định, compile lúc build engine. Bạn được gì Hết jank compile shader khi animation chạy lần đầu. Chữ SDF — glyph sắc hơn trên màn desktop mật độ pixel thấp hơn. Wide Gamut Color mặc định trên macOS khi phần cứng hỗ trợ. Opt-out Skia tạm thời Nền tảng Cách tắt macOS FLTEnableImpeller=false trong Info.plist Windows project.set_impeller_switch(flutter::ImpellerSwitch::Disabled) trong main.cpp Linux fl_dart_project_set_enable_impeller(project, FALSE) trong my_application.cc Hãy file bug. Fallback sẽ bị gỡ. Nên test lại FragmentShader tùy chỉnh và effect nặng saveLayer . Platform view / external texture. Luồng print/export từng giả định color management của Skia. Chạy profile mode trước. Frame vẫn dài thì vẫn là UI vs raster — Impeller chỉ lấy việc ở nhánh compile shader ,...

Impeller is now the default desktop renderer — what actually changes

Mobile Impeller defaults landed earlier. Flutter 3.47 finishes the job on macOS, Windows, and Linux . Desktop apps now target Metal (macOS) and Vulkan (Windows/Linux) with a fixed shader set compiled at engine-build time. What you gain No shader-compilation jank on first run of an animation. Signed Distance Function text — sharper glyphs on lower-density desktop displays. Wide Gamut Color on by default on macOS where hardware supports it. Temporary Skia opt-outs If a regression blocks you: Platform Opt-out macOS FLTEnableImpeller=false in Info.plist Windows project.set_impeller_switch(flutter::ImpellerSwitch::Disabled) in main.cpp Linux fl_dart_project_set_enable_impeller(project, FALSE) in my_application.cc File a bug. Fallbacks are scheduled for removal. What to retest Custom FragmentShader s and saveLayer -heavy effects. Platform views and external textures. Print/export paths that assumed Skia color management. Profile mode first. If a f...

Flutter trên desktop: cửa sổ giờ là một phần của ứng dụng bạn

Một ứng dụng Flutter chạy được trên desktop và một ứng dụng Flutter thuộc về desktop là hai phần mềm khác nhau. Cái thứ nhất là bố cục điện thoại kéo giãn ra 1920 pixel. Cái thứ hai biết cửa sổ của mình có thể bị co lại tới mức phi lý, biết người dùng mong Cmd+W đóng một tab, biết chuột phải phải bật menu ngữ cảnh, và biết cuộn bằng trackpad không phải cùng một cử chỉ với kéo bằng ngón tay. Chẳng có gì trong số này là khó. Nó chỉ là danh sách những thứ mà di động chưa bao giờ bắt bạn nghĩ tới. Cửa sổ có vòng đời do bạn điều khiển Future < void > main () async { WidgetsFlutterBinding . ensureInitialized (); await windowManager. ensureInitialized (); const options = WindowOptions ( size : Size ( 1200 , 800 ), minimumSize : Size ( 720 , 480 ), center : true , titleBarStyle : TitleBarStyle .normal, ); await windowManager. waitUntilReadyToShow (options, () async { await windowManager. show (); await windowManager. focus ()...