Issue
I have an app with many activities, and lots of them hit various json web APIs to load & show data. A common pattern is similar to:
public class MyActivity extends Activity {
public void OnCreate(Bundle savedInstanceState) {
...
ProgressDialog pd = ProgressDialog.show( ... );
// This is a custom API which wraps AsynkTask and calls my callback in onPostExecute
DoWebThing(url, new Callback() {
public void onSuccess(String json) {
pd.dismiss();
// Do other UI stuff with the json data
}
});
}
}
This works great, and is similar to a lot of code snippets you'll find on SO and tutorials. The problem is that the user can leave the page while the background process is running. In this case, I get a logcat error about leaking the view (the ProgressDialog), and then I'll crash when I dismiss it or do my other UI stuff.
I've tried adding an early check in onSuccess:
if (!pd.isShowing()) {
return;
}
This fixes the crash on some devices, but not others, and we still get the logcat error about a leaked view.
I've tried replacing the pd.isShowing()
check with MyActivity.this.isFinishing()
, which doesn't help with anything (on the device I'm currently testing with). Still get the logcat error and crash.
I've tried MyActivity.this.isDestroyed()
, which fixes the crash, but only works on SDK 17+ and still get the logcat error.
The only option to truly fix this is to make my progress dialog a member variable and override OnDestroy()
:
ProgressDialog mPd;
@Override
protected void onDestroy() {
super.onDestroy();
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
Now in my callback I can check if mProgressDialog == null
.
This works great. No crash and no logcat error about leaking a view. But it feels like a lot of boilerplate - I have to make the progress dialog a member variable and override OnDestroy()
in all of my (many) activities that do background stuff.
I'm not seeing a better option, but wanted a second opinion before I start updating lots of activities.
Solution
Create one Activity, say NetworkBaseActivity. Create the ProgressDialog and handle onDestroy in this activity. Also create a method called showMyDialog()
and hideMyDialog()
to show and hide the dialog(from subclasses). Now all your activities that do background stuff only need to extend this activity. To show the dialog call showMyDialog()
and to hide it call hideMyDialog()
Something like this:
public class NetworkBaseActivity extends AppCompatActivity{
ProgressDialog myDialog;
onCreate(Bundle bundle){
// initialize myDialog
}
public void showDialog(){
// show myDialog if not shown
}
public void hideDialog(){
// hide myDialog if already shown
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
public class YourActivity extends NetworkBaseActivity{
}
I typed the code right into stackoverflow so pardon my typos, but you get the idea.
Answered By - nupadhyaya
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.