Pérdida de memoria causada por el controlador de desarrollo de Android

Si define una clase Handler interna en Activity, el siguiente código:

public class MainActivity extends Activity {
     
     
 
    private  Handler mHandler = new Handler() {
     
     
        @Override
        public void handleMessage(Message msg) {
     
     
            //TODO handle message...
        }
    };
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
     
     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler.sendMessageDelayed(Message.obtain(), 60000);
 
        //just finish this activity
        finish();
    }
}

Luego, ejecute la herramienta Android Lint y habrá una advertencia de pérdida de memoria:

This Handler class should be static or leaks might occur (com.example.ta.MainActivity.1)
Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeak
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.

La razón es:

  • Cuando se inicia la aplicación de Android, primero creará un objeto Looper del hilo principal de la aplicación. Looper implementa una cola de mensajes simple y procesa los objetos Mensaje en ella uno por uno. El objeto Looper del hilo principal existe durante todo el ciclo de vida de la aplicación.

  • Cuando el Handler se inicializa en el hilo principal, el Handler se asocia con la cola de mensajes de Looper. El mensaje enviado a la cola de mensajes hará referencia al objeto Handler que envió el mensaje, de modo que el sistema pueda llamar al Handler # handleMessage (Mensaje) para distribuir y procesar el mensaje.

  • En Java, las clases internas no estáticas (anónimas) se refieren a objetos de clase externa. La clase interna estática no hace referencia al objeto de clase externa.

  • Si la clase externa es Actividad, hará que la actividad se filtre.

Cuando finalice la actividad, el mensaje retrasado seguirá existiendo en la cola de mensajes del hilo principal durante 1 minuto, y luego se procesará el mensaje. El mensaje se refiere al objeto Handler de la actividad y luego el Handler se refiere a la actividad. Estos objetos de referencia permanecerán hasta que se procese el mensaje, lo que hará que el objeto Actividad no se pueda reciclar, lo que conduce a la pérdida de Actividad mencionada anteriormente.

Para solucionar este problema, simplemente siga las instrucciones de Lint para definir la clase Handler como estática y luego use WeakReference para mantener el objeto Activity externo.

private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{
     
     
    private final WeakReference<Activity> mActivity;
    public MyHandler(Activity activity) {
     
     
        mActivity = new WeakReference<Activity>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
     
     
        System.out.println(msg);
        if(mActivity.get() == null) {
     
     
            return;
        }
    }
}

Por lo tanto, cuando usa una clase interna en una actividad, debe considerar siempre si puede controlar el ciclo de vida de la clase interna. De lo contrario, es mejor definir una clase interna estática.

Artículo de referencia: http://blog.chengyunfeng.com/?p=468

Supongo que te gusta

Origin blog.csdn.net/xhf_123/article/details/50016555
Recomendado
Clasificación