- Büyük resimler ilk yüklemede max 2048px'e downsampling (RAM ~1.6MB) - Zoom 1.5x stretch'i geçince full-res'e swap (orijinal çözünürlük) - Resim geçişinde eski provider evict + ImageCache.evict() (RAM leak) - Tiled render kodu tamamen kaldırıldı
2.8 KiB
2.8 KiB
Yönerge: Downsampling + Full-Res Swap + RAM Leak Fix
Amaç
Yüksek çözünürlüklü görsellerde RAM tüketimini azaltmak ve resim geçişlerinde bellek sızıntısını gidermek.
Dosya
lib/widgets/image_canvas.dart
1. State değişkenleri ekle
_ImageCanvasState sınıfına aşağıdaki değişkenleri ekle:
ui.Image? _uiImage;
ui.Image? _fullResImage;
bool _fullResLoading = false;
bool _usingFullRes = false;
static const int _downsampleTarget = 2048;
2. _loadUiImage() — Downsample decode
Mevcut _loadUiImage() metodunu aşağıdaki gibi değiştir:
ui.instantiateImageCodec()çağrısınatargetWidth: _downsampleTarget, targetHeight: _downsampleTargetparametrelerini ekle- Decode edilen resmin boyutunu
_uiImageve_tiledImageSizeolarak kaydet - Eğer decode boyutu target'tan büyükse →
_loadFullResImage(bytes)başlat (arka plan) - Eğer decode boyutu target'tan küçükse → resim zaten küçük,
_usingFullRes = trueyap
3. _loadFullResImage() — Arka plan full-res yükleme
Yeni metot:
Future<void> _loadFullResImage(Uint8List bytes) async {
if (_fullResLoading) return;
_fullResLoading = true;
try {
final codec = await ui.instantiateImageCodec(bytes);
final frame = await codec.getNextFrame();
if (mounted && !_usingFullRes) {
setState(() => _fullResImage = frame.image);
} else {
frame.image.dispose();
}
} catch (e) { /* log */ }
finally { _fullResLoading = false; }
}
4. _checkFullResSwap() — Zoom threshold'unda swap
Yeni metot. _handleScroll() içinde _sc güncellendikten sonra çağrılır.
- Downsample resmin ne kadar stretch edildiğini hesapla (
stretchX,stretchY) maxStretch >= 1.5ise:_uiImage?.dispose()_uiImage = _fullResImage_fullResImage = null_tiledImageSizegüncelle_usingFullRes = true
5. _handleScroll() — Swap kontrolü ekle
_sc = newSc; satırından sonra _checkFullResSwap() çağrısı ekle.
6. RAM Leak Fix — didUpdateWidget
Resim değiştiğinde eski tüm referansları temizle:
_uiImage?.dispose();
_fullResImage?.dispose();
_cachedFileImage?.evict();
_cachedProvider?.evict();
_cachedFileImage = null;
_cachedProvider = null;
_cachedPath = null;
_cachedCacheWidth = null;
PaintingBinding.instance.imageCache.evict(FileImage(File(old.filePath)));
7. _resetView() — Tüm state sıfırla
_fullResImage, _fullResLoading, _usingFullRes sıfırlansın.
8. dispose() — Her iki resmi de dispose et
_uiImage?.dispose();
_fullResImage?.dispose();
9. Import
dart:typed_data import'u ekle (Uint8List için).
Sonuç
- İlk yükleme: max 2048px downsample (RAM ~1.6MB)
- Zoom ile yakınlaşınca: full-res swap (~512MB+ büyük resimlerde)
- Resim geçişinde: eski tüm cache dispose + evict