2015-08-12 4 views

risposta

120

Quale sarà l'effetto di questo sulle prestazioni dell'applicazione e della memoria?

Glide offre così tante .with() metodi per un motivo: ne consegue ciclo di vita.

Immaginate uno Fragment aggiunto dinamicamente ad un'attività. Nel suo metodo onCreateView avvia un carico Glide di un'immagine da 3MB. Ora, cosa succede se l'utente preme il pulsante Indietro e il frammento viene rimosso o l'intera attività è chiusa?

  • Se si utilizza with(getActivity().getApplicationContext()) nulla accadrà, tutti 3MBs di dati vengono scaricati e poi decodificati, cache, probabilmente anche impostare al ImageView, che viene poi garbage collection, perché l'unico riferimento ad essa era da interni Glide.
  • Se si utilizza with((Fragment)this) Glide si iscrive agli eventi del ciclo di vita di Fragment e non appena il frammento viene arrestato, tutte le richieste in sospeso devono essere sospese; e una volta distrutto, tutte le richieste in sospeso verranno cancellate. Ciò significa che il download dell'immagine si interromperà a metà strada e non verranno più utilizzate risorse da quel frammento morto.
  • Se si utilizza with(getActivity()) Glide si iscrive agli eventi del ciclo di vita dell'Attività e la stessa cosa accade come sopra, ma solo quando l'attività viene interrotta o distrutta.

Quindi la best practice è usare il contesto/frammento più vicino possibile per evitare il completamento di richieste inutilizzate! (C'è anche un modo manuale per fermare un carico:. Glide.clear(ImageView|Target))


Per applicare questo, in pratica, cercare di utilizzare with(this) quando possibile, ma quando non lo è, come in un adattatore, o di un metodo di caricamento delle immagini centralizzata, passare un RequestManager glide come argomento e utilizzare glide.load(..., ad esempio:

static loadImage(RequestManager glide, String url, ImageView view) { 
    glide.load(url).into(view); 
} 

o adattatore:

class MyAdapter extends WhichEveryOneYouUse { 
    private final RequestManager glide; 
    MyAdapter(RequestManager glide, ...) { 
     this.glide = glide; 
     ... 
    } 
    void getView/onBindViewHolder(... int position) { 
     // ... holder magic, and get current item for position 
     glide.load... or even loadImage(glide, item.url, holder.image); 
    } 
} 

e uso questi da Attività/Frammento:

loadImage(Glide.with(this), url, findViewById(R.id.image)); 
// or 
list.setAdapter(new MyAdapter(Glide.with(this), data)); 
+3

Impressionante spiegazione! Mi ha risparmiato un sacco di tempo per indagare su quale fosse la ragione principale dell'eccezione di OOM. Grazie! – user1774316

+0

Posso passare nel contesto del frammento ad un adattatore come 'mContext' e usare' Glide.with (mContext) ... 'nell'adattatore? – squeeish

+0

@Terence Ovviamente, ma è uguale a 'getActivity()' quindi se si sostituisce il frammento con una transazione le risorse non verranno rilasciate fino a quando l'utente non lascerà completamente l'attività. Se hai bisogno di un 'mContext' per altri motivi (ad es.' GetString') puoi semplicemente usare 'anyView.getContext()'. – TWiStErRob

0

Questo ha funzionato per me durante il caricamento dell'immagine:

if (!this.isFinishing()) { 
     Glide.with(this)... 
}