【问题标题】:Leaked window error with Progress Dialog even after calling dismiss即使在调用解除后,进度对话框也会出现泄漏窗口错误
【发布时间】:2014-04-28 04:01:29
【问题描述】:

我有一个菜单按钮,当我点击它时,它会将一些数据发送到云端。在发送数据时,我会显示一个进度对话框。每件事都很顺利,似乎很好,我可以按我想要的次数多次按下按钮,数据会正确地发送到云端。 但是当我退出活动时,我收到一条错误消息,提示存在窗口泄漏:

com.android.internal.policy.impl.PhoneWindow$DecorView{4321fd38 V.E..... R......D 0,0-1026,288} that was originally added here

“这里”指的是我对进度对话框的贪得无厌。

这是我的代码:

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
progressDialog = ProgressDialog.show(CruiseDetailRollCallActivity.this, "", "Loading...", true);//set up & show progress dialog

switch(item.getItemId()){
case R.id.menu_roll_call_opt_in:
    //saveing something into Parse -- (a database online, check Parse.com if you want more info, but just treat this like I am saving something into the cloud)
    currentUser.put("somethingBoolean", false); 
    currentUser.saveInBackground(new SaveCallback(){

    @Override
    public void done(ParseException e) { //once data has been put into the cloud
        progressDialog.dismiss();//dismiss the dialog
        supportInvalidateOptionsMenu();//refreshes the options menu
    }
    });

    return true;

default:
    return super.onOptionsItemSelected(item);
}
}

我应该提一下,这不会使我的应用程序崩溃,而只是显示错误。我不知道为什么会这样,我觉得我不应该忽略它。

EDIT:发现我的错误。它失败了,因为工作是因为我正在回击操作栏,并且将创建进度对话框但从未关闭,因为它只是在完成的代码中被关闭。

【问题讨论】:

  • 你应该在onStop().中解雇Progress Dialog
  • @SimplePlan 请在下面查看我对您的回答的评论。 onStop() 是可终止的,根据操作系统的决定,onStop() 可能永远不会被执行。

标签: java android parse-platform progressdialog


【解决方案1】:

我的猜测是,当您将CruiseDetailRollCallActivity 传递给currentUser.saveInBackground(new SaveCallback()... 时,您将活动泄漏到currentUser 对象中。您刚刚创建的SaveCallback 类现在具有对活动的强引用。即使您退出该方法,它也永远不会被垃圾收集。您应该使用WeakReference,然后它可以被垃圾回收。

WeakReference<CruiseDetailRollCallActivity> weakRef = new WeakReference<CruiseDetailRollCallActivity>(CruiseDetailRollCallActivity.this)

然后,将 weakRef 传递给 ProgressDialog 构造函数:

progressDialog = ProgressDialog.show(weakRef.get(), "", "Loading...", true);

每当您在 Android 中传递 Context 时,请检查您是否需要 WeakReference,以便对其进行垃圾收集。很容易泄露整个应用程序。

【讨论】:

  • 我不完全理解这一点,因为我在我的应用程序的其他地方运行了类似的代码并且它不会引发错误。但是您的代码确实有效。
  • 你应该修复所有其他代码。您正在导致设备上的内存泄漏。人们不会购买您的应用程序! :)
  • 我写了一篇关于这个问题的博文。学习 WeakReferences 和垃圾收集是值得的,特别是如果您将使用 Android。该系统基本上是为产生内存泄漏而设计的。在过去的几天里,它似乎在 SO 上出现了很多。你可以在这里阅读更长的解释:tmblr.co/ZSJA4p13azutu
  • 编辑:我的错误,它可能确实有效。需要仔细检查。
  • 发现我的错误。它给我这个错误的原因不是因为你上面提到的(尽管我应该看看博客文章并考虑到它)。它失败了,因为工作是因为我正在回击操作栏,并且将创建进度对话框但从未关闭,因为它只是在完成的代码中被关闭。我仍然会将您的答案标记为正确,因为人们可能应该这样处理它。
【解决方案2】:

它失败了,因为工作是因为我正在回击操作栏,并且将创建进度对话框但从未关闭,因为它只是在完成的代码中被关闭。

我搬家了

progressDialog = ProgressDialog.show(CruiseDetailRollCallActivity.this, "", "Loading...", true);//set up & show progress dialog

进入

case R.id.menu_roll_call_opt_in:
//saveing something into Parse -- (a database online, check Parse.com if you want more info, but just treat this like I am saving something into the cloud)
currentUser.put("somethingBoolean", false); 
currentUser.saveInBackground(new SaveCallback(){

@Override
public void done(ParseException e) { //once data has been put into the cloud
    progressDialog.dismiss();//dismiss the dialog
    supportInvalidateOptionsMenu();//refreshes the options menu
}
});

return true;

看起来像这样

case R.id.menu_roll_call_opt_in:
progressDialog = ProgressDialog.show(CruiseDetailRollCallActivity.this, "", "Loading...", true);//set up & show progress dialog
//saveing something into Parse -- (a database online, check Parse.com if you want more info, but just treat this like I am saving something into the cloud)
currentUser.put("somethingBoolean", false); 
currentUser.saveInBackground(new SaveCallback(){

@Override
public void done(ParseException e) { //once data has been put into the cloud
    progressDialog.dismiss();//dismiss the dialog
    supportInvalidateOptionsMenu();//refreshes the options menu
}
});

return true;

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多