【问题标题】:Activity has leaked window - Custom DialogActivity 已泄露窗口 - 自定义对话框
【发布时间】:2016-07-27 10:08:38
【问题描述】:

我正在尝试在 Activity 中显示自定义对话框,但出现此错误。我知道为什么herehere 会出现此错误,并且也知道它的解决方案。但问题是我在我的代码中找不到问题。我花了很多时间在没有运气的情况下找到错误。 我在按钮单击时调用了以下方法

public void changePassword(View view){
    DialogChangePassword dialogChangePassword = new DialogChangePassword(ActivityMyAccount.this);
    dialogChangePassword.show();
    Window window = dialogChangePassword.getWindow();
    window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
    window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}

我在此处显示对话框,而 Activity 应该存在。我的问题;

  1. 我无法在此处关闭对话框,我在 Dialog 类中将其关闭。
  2. 我没有完成活动。如果因为活动结束而发生错误,为什么会结束?
  3. 如果错误不是因为完成活动,那么为什么会出现此错误?
  4. 我有一个NetworkOperation 要在 Dialog 类中执行,它与它有什么关系吗?

这是我的 Dialog 类

public class DialogChangePassword extends Dialog {
    Context context;
    Button confirm, cancel;

    CustomEditText edtOldPwd, edtNewPwd, edtConfirmNewPwd;

    ProgressDialog progressDialog;

    String PASSWORD_INCORRECT_MESSAGE = "Old password is incorrect.";

    public DialogChangePassword(Context context) {
        super(context);
        this.context = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialog_change_password);

        if(progressDialog != null)
            progressDialog = null;

        progressDialog = new ProgressDialog(context);
        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("Updating Password.");
        progressDialog.show();


        confirm = (Button) findViewById(R.id.btnChangePassword);
        cancel = (Button) findViewById(R.id.btnCancel);

        edtOldPwd = (CustomEditText) findViewById(R.id.edtOldPassword);
        edtNewPwd = (CustomEditText) findViewById(R.id.edtNewPassword);
        edtConfirmNewPwd = (CustomEditText) findViewById(R.id.edtConfirmNewPassword);

        edtConfirmNewPwd.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!edtNewPwd.getText().toString().equals(edtConfirmNewPwd.getText().toString()))
                    edtConfirmNewPwd.setError("Password doesn't match");
            }
        });

        confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!edtNewPwd.getText().toString().equals(edtConfirmNewPwd.getText().toString())) {
                    Toast.makeText(context, "Password doesn't match",         Toast.LENGTH_SHORT).show();
                    progressDialog.cancel();
                    return;
                }
                HashMap<String, String> params = new HashMap<>();
                params.put("email", Utility.classUser.getEmailId());
                params.put("password", edtOldPwd.getText().toString());
                params.put("newPassword", edtNewPwd.getText().toString());
                new NetworkOperation().execute(params);
            }
        });
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
    }

    private class NetworkOperation extends AsyncTask<HashMap<String,String>, Void, String> {
        @Override
        protected String doInBackground(HashMap<String, String>... params) {
            try {
                ClassAPIRoutes routes = ClassAPIRoutes.initializeRoutes();
                return routes.editUserPassword(params[0]);
            } catch (final IOException e) {
                e.printStackTrace();
                getOwnerActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show();
                    }
                });
                return "error";
            }
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            progressDialog.cancel();
            dismiss();
            if(!s.equals("error")){
                JSONObject jsonObject;
                try {
                    jsonObject = new JSONObject(s);
                    if (jsonObject.get("success").toString().equals("true")) {
                        Toast.makeText(context, "Password successfully changed.", Toast.LENGTH_SHORT).show();
                        dismiss();
                    } else if (jsonObject.get("success").toString().equals("false")) {
                        if (jsonObject.get("message").toString().equals(PASSWORD_INCORRECT_MESSAGE)) {
                            Toast.makeText(context, PASSWORD_INCORRECT_MESSAGE, Toast.LENGTH_SHORT).show();
                            resetFields();
                        }
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    Toast.makeText(getContext(), s, Toast.LENGTH_SHORT).show();
                }
            }

        }
    }

    private void resetFields(){
        edtOldPwd.setText("");
        edtNewPwd.setText("");
        edtConfirmNewPwd.setText("");
    }

}

【问题讨论】:

  • 在完成活动之前关闭您的对话框/进度对话框/警报对话框,您将不会有任何泄漏:)
  • 您的对话框包含您活动的上下文。正如@SripadRaj 所说,在完成活动之前关闭你的对话框,也许把它放在 onStop 中。
  • @gitter 我想在更改密码后再次返回活动。为什么活动结束?如果是这样,DialogChangePassword 将被解雇,我将无法更改密码。好吧,我试过了,没有运气
  • 嗯。鉴于 AsyncTask 通常因内存泄漏而臭名昭著,因此在对话框中设置 AsyncTask 看起来很容易出错。尝试将您的解雇呼叫移动到 onPostExecute 的末尾一次?
  • 我已经在 onPostExecute() 内部调用了 dismiss()

标签: android memory-leaks dialog


【解决方案1】:

我已经从onCreate(...) 中删除了显示进度对话框,并将其放在OnPreExecute(...) 内的Async 类中,它工作正常

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-16
    • 2016-06-26
    • 2020-06-13
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多