WeakReference în Dart

O referință care nu ține obiectul în viață; target dă obiectul sau null după ce a fost șters din memorie.

Sintaxă
WeakReference(T target)    // T extends Object
T? get target

Ce face WeakReference

O variabilă obișnuită ține obiectul în memorie cât timp există. Un WeakReference „privește” obiectul fără să-l rețină: dacă nu mai există alte referințe la el, colectorul de gunoi (garbage collector) îl poate șterge. target returnează obiectul cât timp există și null după ce a fost șters.

Momentul ștergerii nu este previzibil: poate fi imediat sau mult mai târziu. De aceea verifici mereu target pentru null și nu te bazezi pe când devine null. Ca la Expando, numerele, textele, bool și record-urile nu sunt permise ca țintă.

Se folosește pentru cache-uri care nu trebuie să blocheze eliberarea memoriei, de exemplu imagini mari încărcate o dată și refolosite doar dacă mai sunt în memorie.

Parametri

Parametru Descriere
target Obiectul urmărit.

Ce returnează

target: obiectul sau null.

Exemple

Exemplul 1: target cât timp obiectul este folosit

Cât timp variabila imagine există, obiectul nu poate fi șters, deci target nu este null.

class Imagine {
  final String nume;
  final int kb;
  Imagine(this.nume, this.kb);
}

void main() {
  var imagine = Imagine('harta_iasi.png', 4096);
  var ref = WeakReference(imagine);
  print(ref.target?.nume);
  print(identical(ref.target, imagine));
  try {
    WeakReference<Object>('text');
  } on ArgumentError {
    print('Textele nu pot fi ținte');
  }
}

Rezultat

harta_iasi.png
true
Textele nu pot fi ținte

Exemplul 2: Un cache care nu reține memoria

Dacă imaginea a fost ștearsă între timp, cache-ul o încarcă din nou. Când se întâmplă asta depinde de colectorul de gunoi, așa că rezultatul de mai jos este un exemplu.

class Imagine {
  final String nume;
  Imagine(this.nume) {
    print('încarc $nume de pe disc');
  }
}

final cache = <String, WeakReference<Imagine>>{};

Imagine incarca(String nume) {
  var existenta = cache[nume]?.target;
  if (existenta != null) return existenta;
  var noua = Imagine(nume);
  cache[nume] = WeakReference(noua);
  return noua;
}

void main() {
  var a = incarca('logo.png');
  var b = incarca('logo.png');
  print(identical(a, b));
}

Rezultat posibil (diferă la fiecare rulare)

încarc logo.png de pe disc
true

Greșeli frecvente

  • Folosești ref.target! fără verificare. Obiectul poate dispărea oricând; verifică null.

Comenzi înrudite

  • Expando: Atașează valori suplimentare unor obiecte existente, fără să le modifici clasa și fără să le ții în viață.
  • identical: Verifică dacă două variabile arată spre exact același obiect din memorie, nu doar spre obiecte egale.