8

Use case:

The user start the app that will load a captcha. The user fill the captcha and try to download some information.

Problem:

If the user rotate the device while downloading the Activity is destroyed. At the end of the execution the AsyncTask is trying to update the destroyed Activity and the result is a "View not attached to window manager".

"Wrong" solution:

I can mask the problem with a android:configChanges="orientation|keyboardHidden|screenSize" but with this the layout is not going to be updated to landscape.

What I'm asking:

Is it possible to change the orientation and change the "reference" of the Context passed to the AsyncTask?

This answer suggest to check if the dialog is not null, but it's not what I'm looking for.

Here he suggests to use a WeakReference (here a nice snippet on how to use it) but I didn't understand if it's what I'm looking for.

To be more explicit this is what I'm doing in the onPostExecute:

@Override
protected void onPostExecute(Auto result) {
    progress.dismiss();
    new DownloaderCaptcha(context).execute("");
    ((EditText)context.findViewById(R.id.editTextCaptcha)).setText("");
    context.findViewById(R.id.progrBar).setVisibility(View.VISIBLE);
    context.findViewById(R.id.captcha).setVisibility(View.INVISIBLE);

    if(result != null) {
        Storage.storeHistory(context, result.getTarga().getValue());

        Intent i = new Intent(context, MenuActivity.class);
        i.putExtra("result", result);
        context.startActivity(i);
    } else {
        ErrorDialog.show(context, error);
    }
}
Community
  • 1
  • 1
Enrichman
  • 11,157
  • 11
  • 67
  • 101
  • It's not the best answer but you could keep a ref on your asyncTask and pass it to your landscape activity. The landscape activity would then update asynctask context... But I don't know what will happen if your ascncTask finish during the activity transition (but there are simple solutions to this issue). – Xval Feb 04 '13 at 10:55
  • @matiash: no need to downvote, also because if you look at the time when the answer was posted, it was right after Alex post this one! So at the time there wasn't a good answer to my question. Obviously you can flag it as a duplicate, but a downvote is meant a lack of research, not my case I guess. Just my two cents. – Enrichman Jun 23 '15 at 11:09
  • @Enrichman I didn't downvote it. I agree it's a good question, it's just a duplicate one. – matiash Jun 23 '15 at 14:08
  • @matiash yes, no problem, I thought it was you since the flag. :) – Enrichman Jun 23 '15 at 14:32

2 Answers2

16

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.

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
0

"Wrong" solution:

I can mask the problem with a android:configChanges="orientation|keyboardHidden|screenSize" but with this the layout is not going to be updated to landscape.

Actually it will.

android:configChanges Lists configuration changes that the activity will handle itself. When a configuration change occurs at runtime, the activity is shut down and restarted by default, but declaring a configuration with this attribute will prevent the activity from being restarted. Instead, the activity remains running and its onConfigurationChanged() method is called.

Take a look at http://developer.android.com/guide/topics/manifest/activity-element.html#config

You can implement the layout for both Landscape and Portrait modes or to cancel your AsyncTask on configuration change.

EvZ
  • 11,889
  • 4
  • 38
  • 76
  • Of course I have. It will change the orientation but the layout used is the one defined for the portrait mode. – Enrichman Feb 04 '13 at 10:53