title: Android ViewPager, Fragments and AsyncTask. How do i preserve the AsyncTask's state on orientation change?
body: <p>To begin with; Yes, I've searched for an answer to this everywhere, but no one have had the same problem that i have. This question might seem to be the same as another question on here, but it's most definitely not :)</p>
  
  <p>Basically what i want to create is a "First-start" activity that consists of 4 fragments with different layouts. This I've managed to do myself. I also have an AsyncTask that will help one of the fragments with a call to a remote server to check if a user exists in a database. This also works. BUT, as soon as I rotate the phone and orientation changes the FragmentActivity is recreated (obviously =)). If i do this when I've fired the AsyncTask, it either crashes or in some cases finishes it's user check.</p>
  
  <p>So my question is: <strong>How do I preserve the state of the AsyncTask if orientation changes?</strong>
  I've seen some basic solutions using callbacks and to place the AsyncTask as an inner-class. They don't work in my case due to the layout of my pager adapter and the fact that the same Fragments class is used for all four fragments that's created.</p>
  
  <p>Any help is much appreciated. Examples or solutions are even more appreciated! =)</p>
  
  <p>See below for the (ugly) code that makes all of this come to life.</p>
  
  <p><strong>FirstRunActivity.java</strong></p>
  
  <pre><code>import android.content.Intent;
  import android.os.Bundle;
  import android.support.v4.view.ViewPager;
  
  import com.actionbarsherlock.app.SherlockFragmentActivity;
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuInflater;
  import com.actionbarsherlock.view.MenuItem;
  import com.iqqn.***.R;
  import com.viewpagerindicator.IconPageIndicator;
  import com.viewpagerindicator.PageIndicator;
  
  public class FirstRunActivity extends SherlockFragmentActivity {
  
  private FragmentAdapter mAdapter;
  private ViewPager mPager;
  private PageIndicator mIndicator;
  private boolean userExit = false;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.first_run);
  
      mAdapter = new FragmentAdapter(getSupportFragmentManager());
  
      mPager = (ViewPager)findViewById(R.id.pager);
      mPager.setAdapter(mAdapter);
  
      mIndicator = (IconPageIndicator)findViewById(R.id.indicator);
      mIndicator.setViewPager(mPager);
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getSupportMenuInflater();
      inflater.inflate(R.menu.first_run, menu);
      return super.onCreateOptionsMenu(menu);
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      switch (item.getItemId()) {
      case R.id.menu_exit:
          userExit = true;
          this.finish();
          return true;
      }
      return super.onOptionsItemSelected(item);
  }
  
  @Override
  public void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
  };
  
  @Override
  public void finish() {
      // Prepare data intent 
      Intent data = new Intent();
      if(userExit) {
          data.putExtra("exit", true);
          setResult(RESULT_CANCELED, data);
      } else {
          data.putExtra("signedIn", true);
          data.putExtra("registered", true);
          data.putExtra("acceptedEULA", true);
          // Activity finished ok, return the data
          setResult(RESULT_OK, data);
      }
      super.finish();
  } 
  }
  </code></pre>
  
  <p><strong>FragmentAdapter.java</strong></p>
  
  <pre><code>import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.support.v4.app.FragmentPagerAdapter;
  
  import com.iqqn.***.R;
  import com.viewpagerindicator.IconPagerAdapter;
  
  class FragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
      protected static final int[] CONTENT = new int[] { R.layout.***_welcome_1, R.layout.***_welcome_2, R.layout.***_welcome_3, R.layout.***_welcome_4};
      protected static final String[] CONTENTTITLE = new String[] { "Welcome","Account","Intro","Let's start!" };
  protected static final int[] ICONS = new int[] {
      R.drawable.perm_group_calendar,
      R.drawable.perm_group_camera,
      R.drawable.perm_group_device_alarms,
      R.drawable.perm_group_location
  };
  
  private int mCount = CONTENT.length;
  
  public FragmentAdapter(FragmentManager fm) {
      super(fm);
  }
  
  @Override
  public Fragment getItem(int position) {
      return Fragments.newInstance(CONTENT[position % CONTENT.length],position);
  }
  
  @Override
  public int getCount() {
      return mCount;
  }
  
  @Override
  public CharSequence getPageTitle(int position) {
      return FragmentAdapter.CONTENTTITLE[position % CONTENT.length];
  }
  
  @Override
  public int getIconResId(int index) {
      return ICONS[index % ICONS.length];
  }
  
  public void setCount(int count) {
      if (count &gt; 0 &amp;&amp; count &lt;= 10) {
          mCount = count;
          notifyDataSetChanged();
      }
  }
  }
  </code></pre>
  
  <p><strong>Fragments.java</strong></p>
  
  <pre><code>public final class Fragments extends SherlockFragment {
      private static final String KEY_CONTENT = "Fragments:Content";
  private int position = -1;
  private RegisterAsyncTaskHelper registerTask = null;
  
  public static Fragments newInstance(int content, int position) {
      Fragments fragment = new Fragments();
      fragment.mContent = content;
      fragment.position = position;
      return fragment;
  }
  
  private int mContent = -1;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  
      setRetainInstance(true);
  
      if ((savedInstanceState != null) &amp;&amp; savedInstanceState.containsKey(KEY_CONTENT)) {
          mContent = savedInstanceState.getInt(KEY_CONTENT);
      }
  }
  
  @Override
  public void onPause() {
  
      super.onPause();
  }
  
  @Override
  public void onResume() {
  
      super.onResume();
  }
  
  @Override
  public void onDestroy() {
       if (registerTask != null) {
           registerTask.cancel(false);
       }
      super.onDestroy();
  }
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  
      final View view = inflater.inflate(mContent, container, false);
  
      switch(position) {
      case 0:
          break;
      case 1:
          final Button btnRegister;
          final Button btnLinkToLogin;
  
          btnRegister = (Button) view.findViewById(R.id.btnRegister);
          btnLinkToLogin = (Button) view.findViewById(R.id.btnLinkToLoginScreen);
          // Register Button Click event
          btnRegister.setOnClickListener(new View.OnClickListener() {         
              public void onClick(View localview) {
                  // Execute register task
                  registerTask = new RegisterAsyncTaskHelper(getActivity(), view);
                  if(registerTask != null)
                      registerTask.execute();
              }
          });
  
          // Link to Login Screen
          btnLinkToLogin.setOnClickListener(new View.OnClickListener() {
  
              public void onClick(View view) {
                  // TODO Login
              }
          });
          break;
      case 2:
          break;
      case 3:
          break;
      default:
          break;
      }
  
      return view;
  }
  
  
  @Override
  public void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      outState.putInt(KEY_CONTENT, mContent);
  }
  
  }
  </code></pre>
  
  <p><strong>RegisterAsyncTaskHelper.java</strong></p>
  
  <pre><code>import org.json.JSONException;
  import org.json.JSONObject;
  
  import android.os.AsyncTask;
  import android.support.v4.app.FragmentActivity;
  import android.view.View;
  import android.widget.EditText;
  import android.widget.ProgressBar;
  import android.widget.TextView;
  
  import com.iqqn.***.R;
  import com.iqqn.***.utils.DatabaseHandler;
  import com.iqqn.***.utils.UserFunctions;
  
  public class RegisterAsyncTaskHelper extends AsyncTask&lt;Void, Integer, Void&gt; {
  
  // JSON Response node names
  private static final String KEY_SUCCESS = "success";
  private static final String KEY_ERROR = "error";
  private static final String KEY_ERROR_MSG = "error_msg";
  private static final String KEY_UID = "uid";
  private static final String KEY_NAME = "name";
  private static final String KEY_EMAIL = "email";
  private static final String KEY_CREATED_AT = "created_at";
  
  private View view = null;
  private FragmentActivity activity = null;
  private ProgressBar mProgress;
  
  public RegisterAsyncTaskHelper(FragmentActivity activity, View view) {
      this.view = view;
      this.activity = activity;
      this.mProgress = (ProgressBar) view.findViewById(R.id.registerProgress);
  }
  
  @Override
  protected void onPreExecute() {
      mProgress.setVisibility(View.VISIBLE);
  }
  
  @Override
  protected Void doInBackground(Void... params) {
  
      final EditText inputFullName;
      final EditText inputEmail;
      final EditText inputPassword;
      final TextView registerErrorMsg;
  
      // Importing all assets like buttons, text fields
      inputFullName = (EditText) view.findViewById(R.id.registerName);
      inputEmail = (EditText) view.findViewById(R.id.registerEmail);
      inputPassword = (EditText) view.findViewById(R.id.registerPassword);
      registerErrorMsg = (TextView) view.findViewById(R.id.register_error);
  
  
      String name = inputFullName.getText().toString();
      String email = inputEmail.getText().toString();
      String password = inputPassword.getText().toString();
      UserFunctions userFunction = new UserFunctions();
      JSONObject json = userFunction.registerUser(name, email, password);
  
      // check for login response
      try {
          if (json.getString(KEY_SUCCESS) != null) {
              activity.runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                      registerErrorMsg.setText("");
                  }
              });
  
              String res = json.getString(KEY_SUCCESS); 
              if(Integer.parseInt(res) == 1){
                  // user successfully registred
                  // Store user details in SQLite Database
                  DatabaseHandler db = new DatabaseHandler(activity.getApplicationContext());
                  JSONObject json_user = json.getJSONObject("user");
  
                  // Clear all previous data in database
                  userFunction.logoutUser(activity.getApplicationContext());
                  db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));                        
  
                  /*
                  // Launch Dashboard Screen
                  Intent dashboard = new Intent(ctx, DashboardActivity.class);
                  // Close all views before launching Dashboard
                  dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                  startActivity(dashboard);
                  // Close Registration Screen
                  finish();
                   */
  
              }else{
                  // Error in registration
                  activity.runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          registerErrorMsg.setText("Error occured in registration");
                      }
                  });
              }
          }
      } catch (JSONException e) {
          e.printStackTrace();
      }
      return null;
  }
  
  @Override
  protected void onProgressUpdate(final Integer... values) {
  
  }
  
  @Override
  protected void onPostExecute(final Void result) {
      mProgress.setVisibility(View.GONE);
  }
  }
  </code></pre>
  
  <p>Just to clarify. This code is in no way supposed to look good as of now. But it will after i get this working.</p>
  
  <p>// Alexander</p>