For my app Moustachify Everything, I was getting quite a few 1-star ratings when users got a black screen for the results.
It took me a while to figure out why it was happening. Because I test on WiFi, the images upload quite quickly.
When testing with 3G, I accidentally rotated the screen and the progress dialog was cleared, leaving me with just a black screen and an ad.
When the AsyncTask completes, it updates the image (in the old Activity) but the image in the current Activity is still black.
To fix this, you'll need to keep track of your AsyncTask. It sounds longer than it actually is, but you'll learn some new tricks on the way.
The AsyncTask
If using an anonymous instance of AsyncTask, extract it out into it's own class or into an inner class of the activity. You'll need to be able to store a reference to it somewhere.
Important things to do are:
- Keep a reference to the current activity
- Keep an instance of the ProgressDialog
The Activity
Using onRetainNonConfigurationInstance(), we pass the new Activity the existing information about the AsyncTask.
This is how we update the "current activity" within the AsyncTask.
Important things to note are:
- Keep an instance of your AsyncTask
- Implement onRetainNonConfigurationInstance()
- During onCreate(), check getLastNonConfigurationInstance()
A working example
01.
public
class
SomeActivity
extends
Activity {
02.
private
ProgressAsyncTask m_progressTask;
03.
04.
// This is purely a data storage class for saving information between rotations
05.
private
class
LastConfiguration {
06.
Drawable drawable;
07.
ProgressAsyncTask progressTask;
08.
09.
public
LastConfiguration(Drawable drawable, ProgressAsyncTask progressTask) {
10.
this
.drawable = drawable;
11.
this
.progressTask = progressTask;
12.
}
13.
}
14.
15.
private
class
ProgressAsyncTask
extends
AsyncTask<String, Integer, Bitmap> {
16.
private
ProgressDialog progressDialog;
17.
private
Activity m_activity;
18.
19.
protected
ProgressAsyncTask(Activity activity) {
20.
setActivity(activity);
21.
}
22.
23.
public
void
setActivity(Activity activity) {
24.
m_activity = activity;
25.
26.
progressDialog =
new
ProgressDialog(m_activity);
27.
progressDialog.setMessage(
"Growing your mo ..."
);
28.
progressDialog.setCancelable(
false
);
29.
progressDialog.setMax(
100
);
30.
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
31.
32.
progressDialog.show();
33.
}
34.
35.
// Just some example code to update your progress dialog
36.
protected
void
onProgressUpdate(Integer... values) {
37.
progressDialog.setProgress((
int
) ((values[
0
] / (
float
) values[
1
]) *
100
));
38.
};
39.
40.
// Once we're done, make sure you reference the activity
41.
@Override
42.
protected
void
onPostExecute(Bitmap result) {
43.
ImageView img = (ImageView) m_activity.findViewById(R.id.imgResult);
44.
img.setImageBitmap(result);
45.
progressDialog.hide();
46.
}
47.
}
48.
49.
@Override
50.
protected
void
onCreate(Bundle savedInstanceState) {
51.
super
.onCreate(savedInstanceState);
52.
setContentView(R.layout.result);
53.
54.
// See if we've got any information from the existing Activity
55.
LastConfiguration lastConfiguration = (LastConfiguration)
this
.getLastNonConfigurationInstance();
56.
57.
// Screen was rotated, re-apply data we already have
58.
if
(lastConfiguration !=
null
) {
59.
ImageView img = (ImageView) findViewById(R.id.imgResult);
60.
img.setImageDrawable(lastConfiguration.drawable);
61.
m_progressTask = lastConfiguration.progressTask;
62.
// Update the task because it is currently pointing to a stale activity
63.
m_progressTask.setActivity(
this
);
64.
}
65.
// New instance of SomeActivity, fetch image
66.
else
{
67.
m_progressTask =
new
ProgressAsyncTask(
this
);
68.
m_progressTask.execute(
"<a href="
http:
//www.url.com/to/file.jpg");">http://www.url.com/to/file.jpg");</a>
69.
}
70.
}
71.
72.
// Remember the information when the screen is just about to be rotated.
73.
// This information can be retrieved by using getLastNonConfigurationInstance()
74.
public
Object onRetainNonConfigurationInstance() {
75.
ImageView iv = (ImageView) findViewById(R.id.imgResult);
76.
return
new
LastConfiguration(iv.getDrawable(), m_progressTask);
77.
}
78.
}