问题
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);
}
}
回答1:
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 retainedFragment
s. It solves the problem of retaining anAsyncTask
across a rotation change nicely. You basically need to host yourAsyncTask
inside aFragment
, callsetRetainInstance(true)
on theFragment
, and report theAsyncTask
's progress/results back to it'sActivity
through the retainedFragment
.
回答2:
"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.
来源:https://stackoverflow.com/questions/14685011/handle-orientation-change-with-running-asynctask