How to Handle an Asynctask During Screen Rotation

Best practice: AsyncTask during orientation change

Do NOT use android:configChanges to address this issue. This is very bad practice.

Do NOT use Activity#onRetainNonConfigurationInstance() either. This is less modular and not well-suited for Fragment-based applications.

You can read my article describing how to handle configuration changes using retained Fragments. It solves the problem of retaining an AsyncTask across a rotation change nicely. You basically need to host your AsyncTask inside a Fragment, call setRetainInstance(true) on the Fragment, and report the AsyncTask's progress/results back to it's Activity through the retained Fragment.

How to handle an AsyncTask during Screen Rotation?

My first suggestion would be to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my <activity> tag in the AndroidManifest.xml, and been just fine.

android:configChanges="keyboardHidden|orientation"

It looks weird, but what it does it hand off to your onConfigurationChanged() method, if you don't supply one it just does nothing other than re-measure the layout, which seems to be a perfectly adequate way of handling the rotate most of the time.

How to handle a running AsyncTask during orientation/configuration change?

According to this page : http://developer.android.com/guide/topics/manifest/activity-element.html#config, if your application targets API level 13 or higher, you should use android:configChanges="orientation|screenSize" to catch the screen rotation into the onConfigurationChanged() method.

By doing this, the onPause and onResume methods are not called, so your TextView will keep its value. And in my mind, it won't stop the running AsyncTask. If it does, try to recall it in the onConfigurationChanged method.

Android Fragments. Retaining an AsyncTask during screen rotation or configuration change

Fragments can actually make this a lot easier. Just use the method Fragment.setRetainInstance(boolean) to have your fragment instance retained across configuration changes. Note that this is the recommended replacement for Activity.onRetainnonConfigurationInstance() in the docs.

If for some reason you really don't want to use a retained fragment, there are other approaches you can take. Note that each fragment has a unique identifier returned by Fragment.getId(). You can also find out if a fragment is being torn down for a config change through Fragment.getActivity().isChangingConfigurations(). So, at the point where you would decide to stop your AsyncTask (in onStop() or onDestroy() most likely), you could for example check if the configuration is changing and if so stick it in a static SparseArray under the fragment's identifier, and then in your onCreate() or onStart() look to see if you have an AsyncTask in the sparse array available.

How to work with AsyncTask when screen rotates

i would suggest you to to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my tag in the AndroidManifest.xml, and been just fine.

android:configChanges="keyboardHidden|orientation"

source How to handle an AsyncTask during Screen Rotation?

Handle orientation change with running AsyncTask

Here are my tips:

  • Do not use android:configChanges to address this issue.

  • Do not use Activity#onRetainNonConfigurationInstance() to address it either (as this approach is deprecated).

  • Instead, use a retained worker Fragment. I've recently posted an article describing how to handle configuration changes using retained Fragments. It solves the problem of retaining an AsyncTask across a rotation change nicely. You basically need to host your AsyncTask inside a Fragment, call setRetainInstance(true) on the Fragment, and report the AsyncTask's progress/results back to it's Activity through the retained Fragment.

How to handle an AsyncTask during Screen Rotation?

My first suggestion would be to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my <activity> tag in the AndroidManifest.xml, and been just fine.

android:configChanges="keyboardHidden|orientation"

It looks weird, but what it does it hand off to your onConfigurationChanged() method, if you don't supply one it just does nothing other than re-measure the layout, which seems to be a perfectly adequate way of handling the rotate most of the time.

Update UI from AsyncTask and handle properly screen rotate

You can run the AsyncTask in a retained fragment.

public class TaskFragment extends Fragment {
private Callback mCallback;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setRetainInstance(true);
}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

try {
mCallback = (Callback) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TaskFragment.Callback");
}
}

@Override
public void onDetach() {
super.onDetach();

mCallback = null;
}

public void execute(){
new CounterTask().execute();
}

public interface Callback {
void onTaskUpdate(String value);
}

public class CounterTask extends AsyncTask<Void, String, Void> {
@Override
protected Void doInBackground(Void... params) {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
publishProgress("Hello " + i);
} catch (Exception e) {

}
}
return null;
}

@Override
protected void onProgressUpdate(String... values) {
if(mCallback != null) {
String str = values[0];
mCallback.onTaskUpdate(str);
}
}
}
}

Then, implement the callback in your activity and add the fragment via the fragment manager.

public class SampleActivity extends Activity implements
TaskFragment.Callback {
private static final String TAG_TASK_FRAGMENT = "task_fragment";

private TaskFragment mTaskFragment;

private TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
text = new TextView(this);
text.setText("HELLO");

layout.addView(text);
if (savedInstanceState != null) {
text.setText(savedInstanceState.getString("text"));
}

setContentView(layout);

FragmentManager fm = getFragmentManager();
mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);

if(mTaskFragment == null){
mTaskFragment = new TaskFragment();
fm.beginTransaction()
.add(mTaskFragment, TAG_TASK_FRAGMENT)
.commit();
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("text", text.getText().toString());
}

@Override
protected void onStart() {
super.onStart();
mTaskFragment.execute();
}

@Override
public void onTaskUpdate(String value) {
text.setText(value);
}
}


Related Topics



Leave a reply



Submit