Comportamiento del contexto Android AsyncTask

He estado trabajando con AsyncTasks en Android y estoy tratando un problema.

Tomemos un ejemplo simple, una actividad con una AsyncTask. La tarea en el fondo no hace nada espectacular, solo duerme durante 8 segundos.

Al final de la AsyncTask en el método onPostExecute (), simplemente estoy configurando el estado de visibilidad de un botón en Vista.VISIBLE, solo para verificar mis resultados.

Ahora, esto funciona muy bien hasta que el usuario decide cambiar la orientación de sus teléfonos mientras la AsyncTask está funcionando (dentro de la ventana de suspensión de 8 segundos).

Entiendo el ciclo de vida de la actividad de Android y sé que la actividad se destruye y se recrea.

Aquí es donde entra el problema. La AsyncTask se refiere a un botón y aparentemente contiene una referencia al contexto que inició la AsyncTask en primer lugar.

Yo esperaría que este contexto antiguo (dado que el usuario provocó un cambio de orientación) se volviera nulo y la AsyncTask lanzara un NPE para la referencia al botón que está tratando de hacer visible.

En su lugar, no se lanza NPE, AsyncTask piensa que la referencia del botón no es nula, la establece en visible. ¿El resultado? ¡Nada está pasando en la pantalla!

Actualizar: He abordado esto manteniendo unaWeakReference A la actividad y al cambio cuando se produce un cambio de configuración. Esto es engorroso.

Aquí está el código:

public class Main extends Activity {

    private Button mButton = null;
    private Button mTestButton = null;

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

        mButton = (Button) findViewById(R.id.btnStart);
        mButton.setOnClickListener(new OnClickListener () {
            @Override
            public void onClick(View v) {
                new taskDoSomething().execute(0l);
            }
        });
        mTestButton = (Button) findViewById(R.id.btnTest);   
    }

    private class TaskDoSomething extends AsyncTask<Long, Integer, Integer> 
    {
        @Override
        protected Integer doInBackground(Long... params) {
            Log.i("LOGGER", "Starting...");
            try {
                Thread.sleep(8000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 0;
        }

        @Override
        protected void onPostExecute(Integer result) {
            Log.i("LOGGER", "...Done");
            mTestButton.setVisibility(View.VISIBLE);
        }
    }
}

Intente ejecutarlo y mientras AsyncTask está funcionando, cambie la orientación de su teléfono.

Respuestas a la pregunta(4)

Su respuesta a la pregunta