Android ProgressDialog:泄漏窗口

发布于 2024-11-01 23:23:14 字数 791 浏览 1 评论 0原文

我有一个带有 Tabhost 的活动,所有选项卡均由“活动”表示,其中一个称为“BrowserTab”。

所有这些活动都观察一个 Observable 类 Data。

在 BrowserTab 中,我调用 Data 中的一个方法,该方法从 Internet 检索一些数据。 我想在调用此方法时使用 ProgressDialog 通知用户。 我尝试了这样的操作:

在 BrowserTab 中:

public void loadXML(){
    progressDialog = ProgressDialog.show(this, "", "Loading. Please wait...", true);
    data.loadXML(getUrl());
}

public void update(Observable o, Object arg)
{
    progressDialog.dismiss();
}

在 Data 中:

public void loadXML(String url)
{
    this.xml = new XMLParser().parse(url);
    setChanged();
    notifyObservers();

}

像这样,进度对话框在加载后出现,然后立即再次消失。

当我在数据中的 loadXML(String url) 方法中创建一个新线程时,当通知观察者时,我收到“活动已泄漏窗口”异常。

我已经寻找了这个问题的解决方案,但我就是不知道如何解决这个问题。 有人有想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

错々过的事 2024-11-08 23:23:14

旧答案:: 请检查上次编辑

答案是使用 this.getApplicationContext() 而不是 this

progressDialog = ProgressDialog.show(this.getApplicationContext(), "", "Loading. Please wait...", true);

更多解释如下:

ProgressDialog:如何防止泄漏窗口

编辑

我发现稍后出来
this.getApplicationContext()

始终等于 null,因此我使用 DialogFragment 并向其添加 ProgressBar,而不是使用普通的 ProgressDialog

编辑2
这个答案更好,因为它解决了根本原因。也就是说,承载对话框的窗口在对话框之前被关闭,因此只需要求活动在被关闭之前关闭对话框即可

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

つ可否回来 2024-11-08 23:23:14

尝试用这个改变你的代码..

progressDialog = ProgressDialog.show(getParent(), "", "Loading. Please wait...", true);

Try to change your code with this..

progressDialog = ProgressDialog.show(getParent(), "", "Loading. Please wait...", true);
沉溺在你眼里的海 2024-11-08 23:23:14

我总是使用基于 C++ 的风格方法来解决这个问题。因此,您应该使用进度对话框的 WeakReference(在 C++ 中您有 TWeakObjectPtr)。在单独的线程、asyncTask 等中使用 Wea​​kReference 可确保如果某些参与者作为 GC 清除您的引用,WeakReference.get() 将返回 null。因此,您可以推断您将要使用泄漏的窗口...

这就是它的工作原理。我们可以如下说明基于 asyncTask 的构造函数...

    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()
   }

希望它有所帮助

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文