Fragmentos de Android. Retener una AsyncTask durante la rotación de la pantalla o el cambio de configuración

Estoy trabajando en una aplicación para teléfono inteligente / tableta, usando solo un APK y cargando recursos según sea necesario según el tamaño de la pantalla, la mejor opción de diseño parecía estar usando Fragmentos a través de la ACL.

Esta aplicación ha estado funcionando bien hasta ahora y solo se basa en actividades. Esta es una clase simulada de cómo manejo AsyncTasks y ProgressDialogs en las Actividades para que funcionen incluso cuando se gira la pantalla o se produce un cambio de configuración a mitad de la comunicación.

No cambiaré el manifiesto para evitar la recreación de la Actividad, hay muchas razones por las que no quiero hacerlo, pero principalmente porque los documentos oficiales dicen que no es recomendable y lo he logrado hasta ahora, así que no lo recomiendo esa ruta.

public class Login extends Activity {

    static ProgressDialog pd;
    AsyncTask<String, Void, Boolean> asyncLoginThread;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.login);
        //SETUP UI OBJECTS
        restoreAsyncTask();
    }

    @Override
    public Object onRetainNonConfigurationInstance() {
        if (pd != null) pd.dismiss();
        if (asyncLoginThread != null) return (asyncLoginThread);
        return super.onRetainNonConfigurationInstance();
    }

    private void restoreAsyncTask();() {
        pd = new ProgressDialog(Login.this);
        if (getLastNonConfigurationInstance() != null) {
            asyncLoginThread = (AsyncTask<String, Void, Boolean>) getLastNonConfigurationInstance();
            if (asyncLoginThread != null) {
                if (!(asyncLoginThread.getStatus()
                        .equals(AsyncTask.Status.FINISHED))) {
                    showProgressDialog();
                }
            }
        }
    }

    public class LoginThread extends AsyncTask<String, Void, Boolean> {
        @Override
        protected Boolean doInBackground(String... args) {
            try {
                //Connect to WS, recieve a JSON/XML Response
                //Place it somewhere I can use it.
            } catch (Exception e) {
                return true;
            }
            return true;
        }

        protected void onPostExecute(Boolean result) {
            if (result) {
                pd.dismiss();
                //Handle the response. Either deny entry or launch new Login Succesful Activity
            }
        }
    }
}

Este código funciona bien, tengo alrededor de 10.000 usuarios sin quejas, por lo que parecía lógico copiar esta lógica en el nuevo diseño basado en fragmentos, pero, por supuesto, no funciona.

Aquí está el Fragmento de inicio de sesión:

public class LoginFragment extends Fragment {

    FragmentActivity parentActivity;
    static ProgressDialog pd;
    AsyncTask<String, Void, Boolean> asyncLoginThread;

    public interface OnLoginSuccessfulListener {
        public void onLoginSuccessful(GlobalContainer globalContainer);
    }

    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        //Save some stuff for the UI State
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setRetainInstance(true);
        //If I setRetainInstance(true), savedInstanceState is always null. Besides that, when loading UI State, a NPE is thrown when looking for UI Objects.
        parentActivity = getActivity();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            loginSuccessfulListener = (OnLoginSuccessfulListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnLoginSuccessfulListener");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        RelativeLayout loginLayout = (RelativeLayout) inflater.inflate(R.layout.login, container, false);
        return loginLayout;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //SETUP UI OBJECTS
        if(savedInstanceState != null){
            //Reload UI state. Im doing this properly, keeping the content of the UI objects, not the object it self to avoid memory leaks.
        }
    }

    public class LoginThread extends AsyncTask<String, Void, Boolean> {
            @Override
            protected Boolean doInBackground(String... args) {
                try {
                    //Connect to WS, recieve a JSON/XML Response
                    //Place it somewhere I can use it.
                } catch (Exception e) {
                    return true;
                }
                return true;
            }

            protected void onPostExecute(Boolean result) {
                if (result) {
                    pd.dismiss();
                    //Handle the response. Either deny entry or launch new Login Succesful Activity
                }
            }
        }
    }
}

No puedo usaronRetainNonConfigurationInstance() ya que debe llamarse desde la Actividad y no desde el Fragmento, lo mismo ocurre congetLastNonConfigurationInstance(). He leído algunas preguntas similares aquí sin respuesta.

Entiendo que podría requerir un poco de trabajo para organizar estas cosas correctamente en fragmentos, dicho esto, me gustaría mantener la misma lógica básica de diseño.

¿Cuál sería la forma correcta de retener AsyncTask durante un cambio de configuración? Si sigue ejecutándose, muestre un Diálogo de progreso, teniendo en cuenta que AsyncTask es una clase interna del Fragment y es el Fragment mismo quien invoca AsyncTask. ejecutar()

Respuestas a la pregunta(24)

Su respuesta a la pregunta