Android ProgressDialog: Leaked window
I've got an Activity with a Tabhost, all tabs are represented by Activities, one of them called BrowserTab.
All these Activities observe an Observable class, Data.
In BrowserTab, I call a method in Data, which retrieves some data from the internet. I want to notify the user with a ProgressDialog on calling this method. I tried it like this:
In BrowserTab:
public void loadXML(){
progressDialog = ProgressDialog.show(this, "", "Loading. Please wait..."开发者_运维百科, true);
data.loadXML(getUrl());
}
public void update(Observable o, Object arg)
{
progressDialog.dismiss();
}
In Data:
public void loadXML(String url)
{
this.xml = new XMLParser().parse(url);
setChanged();
notifyObservers();
}
Like this, the ProgressDialog appears áfter loading, to dissapear again immediately.
When I create a new Thread in the loadXML(String url) method in Data, I get a "Activity has leaked window" exception when the Observers are notified.
I've searched for solutions to this problem, but I just can't figure out how to fix this. Anyone an idea?
Old answer:: Please check the last edit
The answer is use this.getApplicationContext() instead of this:
progressDialog = ProgressDialog.show(this.getApplicationContext(), "", "Loading. Please wait...", true);
more explanation is here:
ProgressDialog : how to prevent Leaked Window
Edit
Well I found out later that this.getApplicationContext()
always is equal to null, So I used DialogFragment and add a ProgressBar to it instead of using the ordinary ProgressDialog.
Edit 2 this answer is better as it solves the root cause. Which is that the window that hosts the dialog gets dismissed before the dialog, so simply ask the activity to dismiss the dialog before being dismissed
Try to change your code with this..
progressDialog = ProgressDialog.show(getParent(), "", "Loading. Please wait...", true);
I always use for this issue a C++ based style approach. So, you should use a WeakReference (In C++ you have TWeakObjectPtr) of the progress Dialog. Using a WeakReference inside a separated thread, asyncTask, etc.. ensures you that if some actor as GC clear your reference, WeakReference.get() would return null. Therefore you can infere that you are about to work with a leaked window...
This is how it works. We can illustrate an asyncTask based constructor as follows...
private WeakReference<ProgressDialog> progressDialog;
private final FinishListener listener;
public SaveDataTask(ProgressDialog progressDialog,
@NonNull FinishListener listener) {
this.progressDialog = new WeakReference<>(progressDialog);
this.listener = listener;
}
...
@Override
protected void onPostExecute(Boolean success) {
if (progressDialog.get() != null) {
progressDialog.get().cancel();
}
listener.onSaveFinish()
}
Hope it helps
精彩评论