2012-11-22 14 views
5

Nel codice seguente Eclipse genera un avviso "Questa classe di gestore dovrebbe essere statica o potrebbero verificarsi perdite".Questa classe Handler dovrebbe essere statica o potrebbero verificarsi perdite: handler finale

public class MyActivity extends Activity implements Runnable 
{ 
    final Handler handler = new Handler() 
    { 
     @Override 
     public void handleMessage(Message message) 
     { 
     String sResult = (String) message.obj; 
     if((sResult != null) && (sResult != "")) 
      { 
      MyNonStatic = (TableLayout) findViewById(R.id.tableLayout); // any non-static method 
      } 
     return; 
     } 
    }; 


    public void run() 
    { 
     final Message message = handler.obtainMessage(1, MyFunction(context)); 
     handler.sendMessage(message); 
    } 

    public String MyFunction(Context context) 
    { 
     return "MyNewString"; 
    } 
    } 

Rivedere molti argomenti sul sito, ma non ottenere soluzione. Per favore aiutami per questo codice?

Aggiungi: ho bisogno di chiamare il metodo non statico (ad esempio findViewById()) in handleMessage()!

+0

Questo è più o meno lo stesso di questa domanda: http: // StackOverflow. it/questions/11407943/this-handler-class-should-be-static-or-leaks-might-happen-incominghandler – ThomasW

risposta

2

gestore - Gestore che identifica il thread su cui deve essere eseguita la richiamata. Se null, la callback avverrà dal pool di thread del processo.

Immagina la situazione. Alcune attività chiamano e inseriscono lo non-static inner subclass of Handler. E poi l'attività è distrutta. Ma la classe interna vive.

La classe interna mantiene ancora un collegamento all'attività distrutta, non può essere raccolta tramite garbage collection.

E quindi è necessario renderlo statico.

Fonte: Handlers and memory leaks in Android

+0

Shrikant, ho letto questo argomento in precedenza. Si prega di applicare nel contesto del mio codice con chiamata metodo non statico in handleMessage() ... –

+0

La risposta di Uncle Code Monkey (dal link che ho fornito) ti ha aiutato un po '? – Shrikant

+0

Codice Uncle Code Monkey è utile, ma quando non esiste chiama il metodo non statico in handleMessage(). Quando è necessario chiamare il non-statico, il suo codice non funziona. Posso fare qualcosa di sbagliato? –

2

Da Android lint checks:

 
HandlerLeak 
----------- 
Summary: Ensures that Handler classes do not hold on to a reference to an 
outer class 

Priority: 4/10 
Severity: Warning 
Category: Performance 

In Android, Handler classes should be static or leaks might occur. Messages 
enqueued on the application thread's MessageQueue also retain their target 
Handler. If the Handler is an inner class, its outer class will be retained as 
well. To avoid leaking the outer class, declare the Handler as a static nested 
class with a WeakReference to its outer class. 

prima parte l'avvertimento è dovuto al fatto final Handler handler = new Handler() crea una classe interna anonima. Le classi interne non possono essere create in modo autonomo, hai sempre bisogno di un'istanza esterna. Ricorda come potresti creare questo in Java OuterClass.InnerClass innerObject = outerObject.new InnerClass();. Ogni oggetto di classe interna deve anche mantenere un riferimento all'oggetto esterno Outer.this per accedere ai membri di outer.

La seconda parte è final Message message = handler.obtainMessage(1, MyFunction(context)); ha un handle per la classe del gestore interno (che ha un gestore per la classe di attività esterna). Se questo messaggio dura abbastanza a lungo, non sarà possibile raccogliere i rifiuti della tua attività.

Cosa può bloccare il tuo messaggio in elaborazione? Purtroppo lo strumento non riesce a capirlo, quindi ti avvisa sempre della possibile perdita di memoria. Se sei sicuro di ciò che stai facendo, puoi sopprimere questi messaggi entro il various methods.

Per il vostro caso non sembra una buona idea per fare un ActivityRunnable ma in ogni caso può essere che si dovrebbe usare Handler.post o meglio Activity.runOnUIThread.

4

Ecco un esempio di utilizzo di un riferimento debole e classe del gestore statica per risolvere il problema come consigliato nella documentazione Lint:

public class MyClass{ 

    //static inner class doesn't hold an implicit reference to the outer class 
    private static class MyHandler extends Handler { 
    //Using a weak reference means you won't prevent garbage collection 
    private final WeakReference<MyClass> myClassWeakReference; 

    public MyHandler(MyClass myClassInstance) { 
     myClassWeakReference = new WeakReference<MyClass>(myClassInstance); 
    } 

    @Override 
    public void handleMessage(Message msg) { 
     MyClass myClass = myClassWeakReference.get(); 
     if (myClass != null) { 
     ...do work here... 
     } 
    } 
    } 

    private final MyHandler mHandler = new MyHandler(this); 

    public void getHandler() { 
    return new MyHandler(this); 
    } 
}