Note that there are some explanatory texts on larger screens.

plurals
  1. POAndroid Fragments. Retaining an AsyncTask during screen rotation or configuration change
    text
    copied!<p>I'm working on a Smartphone / Tablet app, using only one APK, and loading resources as is needed depending on screen size, the best design choice seemed to be using Fragments via the ACL.</p> <p>This app has been working fine until now being only activity based. This is a mock class of how I handle AsyncTasks and ProgressDialogs in the Activities in order to have them work even when the screen is rotated or a configuration change occurs mid communication.</p> <p>I will not change the manifest to avoid recreation of the Activity, there are many reasons why I dont want to do it, but mainly because the official docs say it isnt recomended and I've managed without it this far, so please dont recomend that route.</p> <pre><code>public class Login extends Activity { static ProgressDialog pd; AsyncTask&lt;String, Void, Boolean&gt; 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&lt;String, Void, Boolean&gt;) getLastNonConfigurationInstance(); if (asyncLoginThread != null) { if (!(asyncLoginThread.getStatus() .equals(AsyncTask.Status.FINISHED))) { showProgressDialog(); } } } } public class LoginThread extends AsyncTask&lt;String, Void, Boolean&gt; { @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 } } } } </code></pre> <p>This code is working fine, I have around 10.000 users without complaint, so it seemed logical to just copy this logic into the new Fragment Based Design, but, of course, it isnt working.</p> <p>Here is the LoginFragment:</p> <pre><code>public class LoginFragment extends Fragment { FragmentActivity parentActivity; static ProgressDialog pd; AsyncTask&lt;String, Void, Boolean&gt; 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&lt;String, Void, Boolean&gt; { @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 } } } } } </code></pre> <p>I cant use <code>onRetainNonConfigurationInstance()</code> since it has to be called from the Activity and not the Fragment, same goes with <code>getLastNonConfigurationInstance()</code>. I've read some similar questions here with no answer.</p> <p>I understand that it might require some working around to get this stuff organized properly in fragments, that being said, I would like to maintain the same basic design logic.</p> <p><strong>What would be the proper way to retain the AsyncTask during a configuration change, and if its still runing, show a progressDialog, taking into consideration that the AsyncTask is a inner class to the Fragment and it is the Fragment itself who invokes the AsyncTask.execute()?</strong></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload