从另一个 class 关闭自定义对话框

Close a Custom Dialog from another class

我有 3 个 classes,一个在我的 CustomDialog class 中,另一个是非 activity class,我在其中调用我的自定义对话框,还有一个第三个 class 这是我的应用程序 class,我想从中关闭自定义对话框。

自定义对话框class:

public class DCCView extends Dialog {



private final String dCancel= "CANCEL";
private ResultListener listener;
private Button btnCurrency1;
private Button btnCurrency2;
private Button btnCancel;
private TextView tvCurrency1;
private TextView tvCurrency2;
private TextView tvMsg;
private Handler mTimer;
private Response response;


public DCCView(@NonNull Context context) {
    super(context);
}

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.dcc_interface);
    setCancelable(false);
    btn1 = findViewById(R.id.btn1);
    btn2 = findViewById(R.id.btn2);
    btnCancel = findViewById(R.id.btn_cancel);

    tv1 = findViewById(R.id.tv1);
    tv2 = findViewById(R.id.tv2);
    tvMsg = findViewById(R.id.tv_dcc_msg);

    btnCurrency1.setOnClickListener(view -> {
        response = Response.C1;
        cancelAlert();
        listener.onResult(response);
    });

    btnCurrency2.setOnClickListener(view -> {
        response = Response.C2;
        cancelAlert();
        listener.onResult(response);
    });

    btnCancel.setOnClickListener(view -> {
        response = Response.CANCEL;
        cancelAlert();
        listener.onResult(response);
    });
}

public interface ResultListener {
    void onResult(Response response);
}

public void showDCC(String transCurrency, double transAmount, String dccCurrency, String dccAmount,String dataDisplay, @NonNull ResultListener listener) {
    this.listener = listener;
    Handler hnd = new Handler(getContext().getMainLooper());
    hnd.post(() -> {
        showAlert();
        btn1.setText(transCurrency);
        tv1.setText(String.format("%.2f",transAmount));
        btn2.setText(dccCurrency);
        tv2.setText(dccAmount);
        btnCancel.setText(dCancel);
        tvMsg.setText(dataDisplay);
    });
}

public void showAlert() {
    if (!isShowing()) {
        show();
    }
}

public void cancelAlert() {
    dismiss();
}

非activity class:

public class MSG1002{
    private static DCCView mDccView;

   public MSG1002() {
                Handler hnd = new Handler(App.getContext().getMainLooper());
    hnd.post(() -> {
        mDccView = new DCCView(App.getContext());
    });
   }

   public void process(){
   mDccView.showDCC(transactionCurrency, transA, dccCurrency, dccAmount, dataUserDisplay, (DCCView.Response response) -> {
                onDccResponse(response, socketCliente);
            });
   }
        

应用class:

public class App extends Application{
private static DCCView mDCCView;
public static void realCancelAlert() {
    mDCCView.cancelAlert();
}

@Override
public void onCreate() {
    super.onCreate();
    mContext = getApplicationContext();
    mDCCView =new DCCView(mContext);
}
App.realCancelAlert();

因此,当我从 MSG1002 class 调用我的自定义对话框时,该对话框出现并且有效,但是当我使用命令行从 class 应用程序关闭它时 App.realCancelAlert();它没有关闭,我不明白为什么,因为当我调试它时,流程会继续,直到它到达 dismiss() 并执行它但它不会消失。

警告 显示对话的片段或activity负责关闭对话。没有其他 class 应该对此负责。否则,您将走上内存泄漏和难以维护代码的道路。

为什么不关闭?

onCreate 中的 App class 中,您实例化了一个 DCCView 类型的对象并将其存储为 class 的静态变量。假设变量现在指向内存地址 0x1234.

然后在代码的其他地方调用 MSG1002 class 的构造函数。它创建自己的 DCCView 实例作为 new DCCView(App.getContext()); 并将其存储在 MSG1002 class 静态变量中。假设变量现在指向内存地址 0x5678.

这些变量 MSG1002.mDCCViewApp.mDCCView 是两个完全不同的变量,它们保存对 mDCCView 的两个不同实例的引用。这就是为什么它们有不同的地址 0x1234 和 0x5678。尝试关闭 App.mDCCView 不会关闭 MSG1002.mDCCView 对话。

如何修复?

注意:强烈建议不要持有与 UI 相关的静态引用,因为它持有对 Context 值的引用并防止它被垃圾收集应该在什么时候。那就是内存泄漏。

  1. 创建 private static DCCView mDCCView; public 或创建 get/set 方法;
public class App extends Application{
    public static DCCView mDCCView;
    ...
  1. MSG1002 中删除 private static DCCView mDccView; class;
  2. 更新 MSG1002 class 以使用 App.mDccView:
public class MSG1002{

   public MSG1002() {
       Handler hnd = new Handler(App.getContext().getMainLooper());
       hnd.post(() -> {
           App.realCancelAlert();
           App.mDccView = new DCCView(App.getContext());
       });
   }

   public void process(){
       App.mDccView.showDCC(transactionCurrency, transA, dccCurrency, dccAmount, dataUserDisplay, (DCCView.Response response) -> {
                onDccResponse(response, socketCliente);
            });
   }
   ...
}

有关内存泄漏的更多信息:memory leak in android, stack overflow issues on dialogues causing memory leaks (9270 results)