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

Bài đăng

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

Moving Android XML / UIKit apps to Flutter gradually — hướng dẫn Flutter

You do not have to rewrite everything to start with Flutter. 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 Add-to-app first screens and shared navigation contracts. 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ế One high-churn feature is a better pilot than a settings page. 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...

Migrating from React Native to Flutter in 2026 — hướng dẫn Flutter

Big-bang rewrites fail. Strangle features behind a shared shell. 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 Strangler patterns, design system mapping, and risk. 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ế Map design tokens first; ports second. 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 ...

Migrating large apps to Material 3 Expressive — hướng dẫn Flutter

M3 migrations fail when done as big-bang UI rewrites. 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 Component themes, regression goldens, and staged rollout. 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ế Stage by feature flag; use goldens for visual regression. 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ôn...

Brand refreshes without breaking mobile users — hướng dẫn Flutter

Rebrands are migrations. Stage them. 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 Token stages, co-existing themes, and migration UX. 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ế Support old/new themes behind a flag for one release. 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 chỉ dành cho l...

Brand refreshes without breaking mobile users

Rebrands are migrations. Stage them. 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 Token stages, co-existing themes, and migration UX. 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 Support old/new themes behind a flag for one release. 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 boundary. The bo...

Migrating to standalone material_ui and cupertino_ui in Flutter 3.47

Flutter 3.47 ships opt-in standalone design packages at 1.0. Design updates no longer wait on the quarterly SDK train. 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 How to move off SDK-bundled Material/Cupertino with dart fix and the compatibility bridge. 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 Weekly releases, independent upgrades, and a style-neutral core for custom design systems and platform design shocks. 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, t...

Moving Android XML / UIKit apps to Flutter gradually

You do not have to rewrite everything to start with Flutter. 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 Add-to-app first screens and shared navigation contracts. 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 One high-churn feature is a better pilot than a settings page. 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...

Migrating from React Native to Flutter in 2026

Big-bang rewrites fail. Strangle features behind a shared shell. 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 Strangler patterns, design system mapping, and risk. 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 Map design tokens first; ports second. 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...

Migrating large apps to Material 3 Expressive

M3 migrations fail when done as big-bang UI rewrites. 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 Component themes, regression goldens, and staged rollout. 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 Stage by feature flag; use goldens for visual regression. 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 ...

Brand refreshes without breaking mobile users — hướng dẫn Flutter

Rebrands are migrations. Stage them. 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 Token stages, co-existing themes, and migration UX. 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ế Support old/new themes behind a flag for one release. 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 chỉ dành cho l...

Brand refreshes without breaking mobile users

Rebrands are migrations. Stage them. 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 Token stages, co-existing themes, and migration UX. 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 Support old/new themes behind a flag for one release. 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 boundary. The bo...

material_ui và cupertino_ui độc lập: thay đổi gì ở bản 1.0

Material và Cupertino từng bị “đóng băng” bên trong core SDK. Mọi cập nhật design phải đợi nhịp release quarterly của Flutter. Ở Flutter 3.47, cả hai thư viện đạt 1.0 dạng package độc lập trên pub.dev: material_ui và cupertino_ui . Bản trong SDK vẫn còn ở release này. Package là opt-in . Đó là chủ đích — team đóng contribution từ tháng 4 để đường migrate nhàm chán nhất có thể. Vì sao cần tách trong năm 2026 Release design hàng tuần. Bugfix và component mới không còn chờ flutter upgrade . Upgrade độc lập. App ghim SDK cũ vẫn update được look-and-feel mới. Core trung lập style. Nền tảng gọn hơn cho design system riêng (và cú sốc Liquid Glass / M3 Expressive từ vendor). Migrate bằng dart fix flutter pub add material_ui # nếu dùng Cupertino: flutter pub add cupertino_ui dart fix --apply --code=migrate_design_widgets Lệnh này rewrite import từ package:flutter/material.dart / cupertino.dart sang package mới. Nếu pubspec.yaml không tự đổi (bug sớm đã biết), thê...

Standalone material_ui and cupertino_ui: what the 1.0 split changes

Material and Cupertino used to be frozen inside the core SDK. That made design updates wait on the quarterly Flutter release train. In Flutter 3.47 both libraries reach 1.0 as standalone packages on pub.dev: material_ui and cupertino_ui . You still get the SDK copies this release. The packages are opt-in . That is deliberate — the team froze contributions in April so the migration path could be boring. Why the split matters in 2026 Three concrete outcomes: Weekly design releases. Bugfixes and new components no longer wait for flutter upgrade . Independent upgrades. An app pinned to an older SDK can still take the latest look and feel. Style-neutral core. A leaner foundation for custom design systems (and for Liquid Glass / M3 Expressive-style shocks from platform vendors). Migrate with dart fix flutter pub add material_ui # if you use Cupertino: flutter pub add cupertino_ui dart fix --apply --code=migrate_design_widgets The fix rewrites imports from packag...

The UIScene migration: the iOS change that will crash unmigrated Flutter apps

Most Flutter migrations are optional until they are annoying. This one is different: once Apple enforces the requirement, apps that have not adopted the UIScene lifecycle will crash on startup . Not degrade. Crash. Apple requires UIKit apps built with the latest SDK to use the UIScene lifecycle starting in the release following iOS 26. Apple has not announced the exact enforcement date. Flutter has supported the migration since 3.38 , and 3.47 makes the surrounding platform changes concrete by raising the floors: iOS 13 → 15 and macOS 10.15 → 12 , to support Xcode 27. What UIScene actually changes The conceptual shift is a split of responsibilities that used to live in one object: AppDelegate now handles process events and overall application lifecycle UISceneDelegate handles UI lifecycle — foreground, background, active, resign Two consequences follow, and both break code: Plugin registration moves. Register in didInitializeImplicitFlutterEngine , not application:didFini...

Migrating to material_ui and cupertino_ui: the design system leaves the SDK

For nine years, import 'package:flutter/material.dart'; has been the first line of almost every Flutter file ever written. Flutter 3.47 begins ending that. material_ui and cupertino_ui are now standalone packages on pub.dev , both at 1.0, both published by the verified flutter.dev publisher. The copies inside the SDK still work — and are scheduled for formal deprecation in the November stable release . This is a bigger change than the diff suggests, so it is worth understanding the reasoning before you run the migration tool. Why decouple at all The Q2 2026 survey answers this more clearly than any blog post. Across every focus area, satisfaction is high: Dart at 92%, Android at 91%, the core framework at 90% . One number breaks the pattern — Cupertino widgets at 61%, down 6 points , the lowest-rated area in the survey. The structural cause is release cadence. Bound to the SDK, Cupertino could only ship fixes on the quarterly stable train. Apple ships design changes whe...

Migrate UIScene: thay đổi iOS sẽ làm app Flutter chưa chuyển bị crash

Phần lớn các cuộc migrate trong Flutter là tuỳ chọn cho tới khi chúng gây phiền. Cái này khác: khi Apple bắt đầu cưỡng chế, app chưa áp dụng vòng đời UIScene sẽ crash ngay lúc khởi động . Không phải giảm chất lượng. Là crash. Apple yêu cầu app UIKit build bằng SDK mới nhất phải dùng vòng đời UIScene kể từ bản phát hành sau iOS 26. Apple chưa công bố ngày cưỡng chế chính xác. Flutter đã hỗ trợ migrate từ 3.38 , và 3.47 làm các thay đổi nền tảng xung quanh trở nên cụ thể bằng cách nâng sàn: iOS 13 → 15 và macOS 10.15 → 12 , để hỗ trợ Xcode 27. UIScene thực sự thay đổi điều gì Sự dịch chuyển về khái niệm là việc tách trách nhiệm vốn nằm trong một đối tượng: AppDelegate giờ xử lý sự kiện tiến trình và vòng đời tổng thể của ứng dụng UISceneDelegate xử lý vòng đời UI — foreground, background, active, resign Hai hệ quả đi kèm, và cả hai đều làm hỏng code: Đăng ký plugin dời chỗ. Đăng ký trong didInitializeImplicitFlutterEngine , không phải application:didFinishLaunchingWithOptio...