Android Fragments. Le maintien d'une AsyncTask au cours de la rotation de l'écran ou de la modification de la configuration

Je suis en train de travailler sur un Smartphone /Tablette application, en utilisant un seul APK, et le chargement des ressources nécessaires en fonction de la taille de l'écran, le meilleur choix de conception qui semblait être à l'aide de Fragments via les ACL.

Cette application a été fonctionne bien jusqu'à maintenant uniquement basée sur l'activité. C'est une maquette de la classe de la façon dont je gère AsyncTasks et ProgressDialogs dans les Activités afin de les faire travailler, même lorsque l'écran est mis en rotation ou un changement de configuration se produit en milieu de communication.

Je ne vais pas changer le manifeste pour éviter de loisirs de l'Activité, il existe de nombreuses raisons pour lesquelles je ne veux pas le faire, mais surtout parce que les docs officielles dire qu'il n'est pas recommandé, et j'ai réussi sans cette mesure, de sorte s'il vous plaît ne recommandons que la route.

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
}
}
}
}

Ce code fonctionne très bien, j'ai autour de 10.000 utilisateurs, sans plainte, il m'a donc semblé logique de simplement copier cette logique dans le nouveau Fragment de Base de Conception, mais, bien sûr, il ne fonctionne pas.

Ici est la LoginFragment:

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
}
}
}
}
}

Je ne peux pas utiliser onRetainNonConfigurationInstance() puisqu'elle doit être appelée à partir de l'Activité et non le Fragment, en va de même avec getLastNonConfigurationInstance(). J'ai lu quelques questions similaires ici sans réponse.

Je comprends qu'il pourrait exiger de travailler autour pour obtenir ce genre de choses bien organisé dans les fragments, cela étant dit, je tiens à maintenir la même conception de base de la logique.

Ce serait le bon moyen de conserver les AsyncTask lors d'un changement de configuration, et s'il est toujours en cours d'exécution, montrent une progressDialog, en prenant en considération le fait que l'AsyncTask est un intérieur de classe pour le Fragment et c'est le Fragment lui-même qui invoque l'AsyncTask.execute()?

InformationsquelleAutor blindstuff | 2011-12-07