从另一个 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.mDCCView
和 App.mDCCView
是两个完全不同的变量,它们保存对 mDCCView
的两个不同实例的引用。这就是为什么它们有不同的地址 0x1234 和 0x5678。尝试关闭 App.mDCCView
不会关闭 MSG1002.mDCCView
对话。
如何修复?
注意:强烈建议不要持有与 UI 相关的静态引用,因为它持有对 Context
值的引用并防止它被垃圾收集应该在什么时候。那就是内存泄漏。
- 创建
private static DCCView mDCCView;
public 或创建 get/set 方法;
public class App extends Application{
public static DCCView mDCCView;
...
- 从
MSG1002
中删除 private static DCCView mDccView;
class;
- 更新
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)。
我有 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.mDCCView
和 App.mDCCView
是两个完全不同的变量,它们保存对 mDCCView
的两个不同实例的引用。这就是为什么它们有不同的地址 0x1234 和 0x5678。尝试关闭 App.mDCCView
不会关闭 MSG1002.mDCCView
对话。
如何修复?
注意:强烈建议不要持有与 UI 相关的静态引用,因为它持有对 Context
值的引用并防止它被垃圾收集应该在什么时候。那就是内存泄漏。
- 创建
private static DCCView mDCCView;
public 或创建 get/set 方法;
public class App extends Application{
public static DCCView mDCCView;
...
- 从
MSG1002
中删除private static DCCView mDccView;
class; - 更新
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)。