2012-08-06 16 views
8

Teniendo en cuenta este código:Android: llamar a los métodos no estáticos de una clase Handler estática

public class MainActivity extends FragmentActivity implements ActionBar.TabListener { 

public static final int MESSAGE_NOT_CONNECTED = 1; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main_layout); 
} 

// ------------------------------------------------- 
public final void setStatus(int Rid) { 
    final ActionBar actionBar = getActionBar(); 
    actionBar.setSubtitle(Rid); 
} 

// ------------------------------------------------- 
static Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MESSAGE_NOT_CONNECTED: 
      setStatus(R.string.title_not_connected); 
      break; 
     } 
    } 
} 
} 

que estoy recibiendo el error de compilación: No se puede hacer una referencia estática al método no estático setStatus (int) ..

Lo cual tiene sentido, porque getActionBar() en setStatus() es un método no estático.

Hice la clase Handler estática debido a la advertencia: Esta clase de Handler debe ser estática o pueden producirse fugas.

La pregunta: ¿cómo accedo correctamente al método setStatus() desde el controlador estático?

EDITAR: el nuevo código de controlador es la respuesta.

static class hHandler extends Handler { 
    private final WeakReference<MainActivity> mTarget; 
    hHandler(MainActivity target) { 
     mTarget = new WeakReference<MainActivity>(target); 
    } 

    @Override 
    public void handleMessage(Message msg) { 
     MainActivity target = mTarget.get(); 
     If(target == null) { 
      return; 
     } 
     switch (msg.what) { 
     case MESSAGE_NOT_CONNECTED: 
      target.setStatus(R.string.title_not_connected); 
      break; 
     } 
    } 
} 
+1

http://stackoverflow.com/q/11407943/844882 –

+0

El enlace que @Alex Lockwood proporcionó, conduce a otro enlace de Romain Guy que me ayudó a entender WeakReferences: clases internas estáticas vs no estáticas [enlace] (https://groups.google.com/forum/?fromgroups#!msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ). Puedo responder mi propia pregunta, pero aún no puedo publicarla. – vedavis

+0

He respondido la pregunta (ya que aparentemente no puede publicarla aún ...): P –

Respuesta

9

Trate de usar un WeakReference, como se describe en este article.

+0

Esa es la respuesta. Edité la publicación original con los cambios. Gracias por publicar, Alex. – vedavis

+0

@Alex Lockwood Ese artículo es bueno, pero no explica cómo obtener un contexto del controlador estático. Estaba usando un Toast desde adentro handleMessage usando Toast.makeText (getApplicationContext(), dataString, Toast.LENGTH_SHORT) .show(); Ahora que Handler es estático, getApplicationContext() no tiene sentido. My Handler está dentro de un Servicio si eso es importante. –

+0

@DavidDoria Otorgue al 'Handler' un constructor que toma un 'Contexto' como argumento y luego contiene una referencia débil a ese 'Contexto'. –

1

Dado que ahora está utilizando un WeakReference, mTarget.get() podría devolver null. En el código editado, no está comprobando si target es null antes de ejecutar target.setStatus(R.string.title_not_connected). Así que esto puede arrojar un NullPointerException si el objeto de referencia débil ha sido GC'ed.

+0

Gracias. Lo tendré en mente. Vernon. – vedavis

0

En el método OnDestroy de mi actividad llamo:

this.myHandler.removeCallbacksAndMessages(null); 

Esto no se deshace de la "clase Esta guía debería ser estáticos o fugas podrían ocurrir" advertencia, pero creo que destruye el mensaje, por lo tanto detener el fuga. Mi clase de controlador es una clase interna no estática de mi actividad. Mi actividad tiene una instancia de MyHandler myHandler.

Cuando hago esto, no se llama al método handleMessage del controlador, lo que supongo que significa que el mensaje que contiene el controlador, que contenía una referencia a la actividad, se destruyó. Estoy abierto para comentarios ya que no lo he probado con ninguna herramienta de prueba de fugas. Aquí es donde copié la idea: http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html contestador: CyrilJanuary 15, 2013 a las 7:50 AM

Cuestiones relacionadas