Je travaille sur une application pour smartphone / tablette, en utilisant un seul APK et en chargeant les ressources selon les besoins en fonction de la taille de l'écran, le meilleur choix de conception semblait être d'utiliser des fragments via l'ACL.
Cette application fonctionnait bien jusqu'à présent, étant uniquement basée sur l'activité. Ceci est une classe simulée de la façon dont je gère les AsyncTasks et ProgressDialogs dans les activités afin de les faire fonctionner même lorsque l'écran est pivoté ou qu'un changement de configuration se produit au milieu de la communication.
Je ne changerai pas le manifeste pour éviter la recréation de l'activité, il y a de nombreuses raisons pour lesquelles je ne veux pas le faire, mais principalement parce que la documentation officielle dit que ce n'est pas recommandé et que je me suis débrouillé sans cela jusqu'à présent, alors veuillez ne pas le recommander 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 bien, j'ai environ 10 000 utilisateurs sans se plaindre, il semblait donc logique de simplement copier cette logique dans la nouvelle conception basée sur les fragments, mais, bien sûr, cela ne fonctionne pas.
Voici le 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 l'utiliser onRetainNonConfigurationInstance()
car il doit être appelé à partir de l'activité et non du fragment, il en va de même getLastNonConfigurationInstance()
. J'ai lu des questions similaires ici sans réponse.
Je comprends que cela pourrait nécessiter un peu de travail pour organiser correctement ces éléments en fragments, cela étant dit, je voudrais conserver la même logique de conception de base.
Quelle serait la bonne façon de conserver l'AsyncTask pendant un changement de configuration, et si elle est toujours en cours d'exécution, afficher un progressDialog, en tenant compte du fait que l'AsyncTask est une classe interne du Fragment et que c'est le Fragment lui-même qui invoque l'AsyncTask.execute ()?