English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Analisi superficiale delle cause e delle misure di prevenzione del overflow di memoria in Android

Questo esempio spiega le tecniche di programmazione Android per il sovraccarico della memoria e le misure preventive. Condivido con tutti per riferimento, come segue:

 Il virtual machine di Android è basato su register Dalvik, la sua dimensione massima heap è generalmente 16M. Ma Android è scritto in Java, quindi in gran parte, il meccanismo di memoria di Android è equivalente al meccanismo di memoria di Java, e i problemi di limitazione della memoria possono portare a gravi problemi come il memory overflow durante lo sviluppo iniziale. Quando non utilizziamo alcune memorie, dobbiamo cercare di evitare di salvare lo stato necessario su piattaforme come Android durante l'esecuzione di altri programmi, in modo che i processi inattivi possano causare problemi di memoria. Dovrebbe essere liberato il più possibile quando si chiude il programma o si salva lo stato, in modo da migliorare la fluidità del sistema in esecuzione.

La memoria di Android si manifesta principalmente:

1. Sull'platforma Android, mantenere a lungo alcune referenze a risorse può causare che alcune memorie non possano essere liberate, portando a molti problemi di memory leak. Ad esempio: Context (nei seguenti paragrafi, Activity è menzionata come Context), quando devi mantenere lo stato dell'oggetto della tua prima classe e trasmetterlo a un altro oggetto della classe, devi liberare prima l'oggetto ricevente prima di eliminare l'oggetto della prima classe. Un punto da notare è che, nel meccanismo di memoria di Java o Android, il nodo di punta deve essere garantito che non venga chiamato da altri oggetti prima di essere liberato dal sistema GC. Vediamo un altro pezzo di codice:

@Override
protected void onCreate(Bundle state) {
   super.onCreate(state);
   TextView label = new TextView(this);
   label.setText("Leaks are bad");
   setContentView(label);
{}

Il significato di questo codice è che carichiamo un'istanza di TextView nel nostro Activity in esecuzione (Context), quindi, attraverso il meccanismo di recupero della GC, sappiamo che per liberare il Context, dobbiamo prima liberare alcuni degli oggetti a cui fa riferimento. Senza di loro, quando cerchi di liberare il Context, troverai una grande quantità di memoria in eccesso. Pertanto, accidentalmente, il memory overflow è un evento molto facile da verificare. Anche l'archiviazione di alcuni oggetti può causare memory leak. Un esempio semplice è il Bitmap, per esempio: quando la schermata si ruota, distrugge lo stato corrente dell'Activity mantenuto e richiede la creazione di una nuova Activity, fino a quando lo stato della nuova Activity non viene salvato. Vediamo un altro pezzo di codice:

private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Le perdite sono cattive");
if (sBackground == null) {
   sBackground = getDrawable(R.drawable.large_bitmap);
{}
label.setBackgroundDrawable(sBackground);
setContentView(label);
{}

Questo codice è molto veloce ma anche sbagliato. La perdita di memoria è facile apparire nella direzione di trasferimento dello schermo. Anche se vediamo che non c'è una salvataggio esplicito dell'istanza Context, quando colleghiamo un'immagine disegnata a una vista, il Drawable viene impostato come callback dal View, il che significa che nel codice sopra, nel momento in cui disegniamo TextView all'interno dell'attività, abbiamo già fatto riferimento a questa attività. La situazione di collegamento può manifestarsi come: Drawable->TextView->Context.

Quindi, quando si desidera rilasciare il Context, è ancora conservato nella memoria e non è stato liberato.

Come evitare questa situazionePrincipalmente riguarda. La thread è più facile sbagliare. Non sottovalutare la thread, in Android la thread è più facile causare perdita di memoria. La principale ragione della perdita di memoria della thread è che il ciclo di vita della thread non è controllabile. Di seguito c'è un pezzo di codice:

public class MyTest extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new MyThread().start();
  {}
  private class MyThread extends Thread{
    @Override
    public void run() {
      super.run();
      //fare qualcosa
    {}
  {}
{}

Il codice è semplice, ma ci sono nuovi problemi su Android, quando passiamo tra le schermate di visualizzazione (orizzontale e verticale), viene nuovamente creato l'Activity orizzontale o verticale. Immaginiamo che l'Activity precedentemente creata venga riutilizzata, ma cos'è successo davvero? Il meccanismo Java non ti darà la stessa sensazione, poiché prima di rilasciare l'Activity, poiché la funzione run non è terminata, quindi MyThread non è stato distrutto, quindi l'Activity (Mytest) che lo utilizza non è stata distrutta nemmeno, portando così a problemi di perdita di memoria.

Alcuni preferiscono utilizzare AsyncTask fornito da Android, ma in realtà i problemi di AsyncTask sono più gravi. Thread si verifica questo problema di perdita di memoria solo quando la funzione run non termina, tuttavia, il meccanismo di implementazione interno di AsyncTask utilizza ThreadPoolExecutor, il cui ciclo di vita degli oggetti Thread è incerto e non controllabile dall'applicazione. Pertanto, se AsyncTask è una classe interna dell'Activity, è più facile verificarsi problemi di perdita di memoria.

I modi di miglioramento dei problemi di thread includono:

① Converti la classe interna del thread in una classe interna statica.
② Cerca di utilizzare riferimenti deboli per conservare Context nel programma.

2. Il bitmap è molto fastidioso...

Bitmap è un oggetto molto fastidioso, per un oggetto di memoria, se l'oggetto occupa troppa memoria e supera i limiti di memoria del sistema, il problema di perdita di memoria è molto evidente.
La soluzione principale per bitmap è evitare di conservare in memoria o ridurre la risoluzione di campionamento. In molti casi, poiché la risoluzione dei pixel delle nostre immagini è molto alta, e non è necessario un'alta risoluzione per il dimensionamento dello schermo del telefono, possiamo prima ridurre la risoluzione di campionamento delle immagini e poi eseguire le operazioni UI originali.

Se non è necessario conservare riferimenti all'oggetto bitmap, possiamo anche utilizzare riferimenti deboli come sostituto. Ci sono molti esempi di codice specifici su Google.

In sintesi, per evitare perdite di memoria, è necessario seguire i seguenti punti principali:

Primo: non conservare a lungo riferimenti a Context (se devi referenziare Context, fai sì che l'oggetto di riferimento e il suo ciclo di vita siano coerenti).

Secondo: se devi utilizzare Context, preferisci utilizzare ApplicationContext per sostituire Context, poiché il ciclo di vita di ApplicationContext è più lungo e non causerebbe problemi di perdita di memoria in condizioni di riferimento.

Terzo: evita di utilizzare variabili statiche nelle Activity quando non controlli il ciclo di vita degli oggetti. Preferisci utilizzare WeakReference per sostituire una statica.

Quarto: Il garbage collector non garantisce di poter recuperare correttamente la memoria, quindi, quando si utilizza il contenuto necessario, è necessario gestire principalmente il ciclo di vita e rilasciare prontamente gli oggetti non necessari. Cerca di rilasciare gli altri oggetti ai quali facciamo riferimento nel metodo onDestroy alla fine della vita dell'Activity, ad esempio: cursor.close().

In realtà, possiamo completare i programmi con meno codice in molti aspetti. Ad esempio, possiamo utilizzare più immagini 9patch. Ci sono molti dettagli che valgono la pena di essere scoperti e sfruttati per problemi di memoria. Se我们能遵循C/C++程序中“谁创建,谁释放”的原则,那么我们对内存的控制并不比Java或Android本身的GC机制差,而且能更好地控制内存,使我们的手机运行得更流畅。

Per coloro che sono interessati a ulteriori contenuti relativi a Android, è possibile consultare le sezioni speciali di questo sito: 'Riassunto delle tecniche di memoria e cache per lo sviluppo Android', 'Tutorial di introduzione e avanzamento per lo sviluppo Android', 'Riassunto delle tecniche di debug e soluzioni ai problemi comuni per lo sviluppo Android', 'Riassunto delle tecniche di operazioni multimediali per Android (audio, video, registrazione, ecc.)', 'Riassunto dell'uso dei componenti base di Android', 'Riassunto delle tecniche di View di Android', 'Riassunto delle tecniche di layout di Android' e 'Riassunto dell'uso dei controlli di Android'.

Spero che l'articolo descritto possa essere utile per la progettazione di applicazioni Android di tutti.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright spetta ai rispettivi autori, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato elaborato manualmente e non assume alcuna responsabilità legale. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare