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

Bài đăng

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

Image caching and decode budgets in Flutter lists — hướng dẫn Flutter

Image decode is one of the most common raster-thread hogs in feed apps. 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 precache, ResizeImage, and avoiding 12MP avatars in chat lists. 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ế Always decode near display size, not camera size. 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 failu...

Image caching and decode budgets in Flutter lists

Image decode is one of the most common raster-thread hogs in feed apps. 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 precache, ResizeImage, and avoiding 12MP avatars in chat lists. 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 Always decode near display size, not camera size. 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...

Image caching and decode budgets in Flutter lists — hướng dẫn Flutter

Image decode is one of the most common raster-thread hogs in feed apps. 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 precache, ResizeImage, and avoiding 12MP avatars in chat lists. 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ế Always decode near display size, not camera size. 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 failu...

Image caching and decode budgets in Flutter lists

Image decode is one of the most common raster-thread hogs in feed apps. 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 precache, ResizeImage, and avoiding 12MP avatars in chat lists. 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 Always decode near display size, not camera size. 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 Flutter image pipeline: from a URL to pixels on screen

Image.network(url) is one of the friendliest APIs in Flutter and one of the easiest to be defeated by. It works immediately, and then a month later you have images that flash white on every rebuild, a gallery that reloads on scroll-back, and 400 MB of memory on a device with 3 GB. All three are the same misunderstanding: Image is a widget, but the caching and decoding happen in an object it delegates to — the ImageProvider . Knowing what that object keys on, and what it caches, explains everything. The five stages Key. The ImageProvider produces a key — for NetworkImage , the URL plus scale. Two providers with equal keys are the same image as far as the cache is concerned. Fetch. Bytes come from the network, an asset bundle, a file, or memory. Decode. Compressed bytes become a dart:ui.Image : raw pixels, width × height × 4 bytes. Cache. The decoded image goes into PaintingBinding.instance.imageCache , keyed on step 1. Paint. The widget draws it, applying fit , alignmen...

The Flutter image pipeline: from a URL to pixels on screen

Image.network(url) is one of the friendliest APIs in Flutter and one of the easiest to be defeated by. It works immediately, and then a month later you have images that flash white on every rebuild, a gallery that reloads on scroll-back, and 400 MB of memory on a device with 3 GB. All three are the same misunderstanding: Image is a widget, but the caching and decoding happen in an object it delegates to — the ImageProvider . Knowing what that object keys on, and what it caches, explains everything. The five stages Key. The ImageProvider produces a key — for NetworkImage , the URL plus scale. Two providers with equal keys are the same image as far as the cache is concerned. Fetch. Bytes come from the network, an asset bundle, a file, or memory. Decode. Compressed bytes become a dart:ui.Image : raw pixels, width × height × 4 bytes. Cache. The decoded image goes into PaintingBinding.instance.imageCache , keyed on step 1. Paint. The widget draws it, applying fit , alignmen...