Android 为什么我在试图显示自定义类中的对话框时被窗口泄漏?
我正在尝试创建一个Android 为什么我在试图显示自定义类中的对话框时被窗口泄漏?,android,android-alertdialog,Android,Android Alertdialog,我正在尝试创建一个警报对话框,我已经做了几百次了,但这次它不起作用。我的活动中的onResume()方法中有以下代码: @Override protected void onResume() { super.onResume(); if (DEBUG) Log.i("BrazoRobot", "onResume()"); isSystemRdy = false; mBluetoothHelper = new BluetoothHelper(thi
警报对话框
,我已经做了几百次了,但这次它不起作用。我的活动中的onResume()
方法中有以下代码:
@Override
protected void onResume() {
super.onResume();
if (DEBUG)
Log.i("BrazoRobot", "onResume()");
isSystemRdy = false;
mBluetoothHelper = new BluetoothHelper(this, bluetoothName);
mBluetoothHelper.connect();
mBluetoothHelper.setOnBluetoothConnected(this);
}
已正确创建不是活动类的对象BluetoothHelper
,我正在将活动上下文传递给它:
public BluetoothHelper (final Context ctx, final String bluetoothName) {
mActivity = ((Activity)ctx);
this.ctx = ctx;
this.bluetoothName = bluetoothName;
}
问题出在我创建对话框的connect()
方法上:
if (!mBluetoothAdapter.isEnabled()) {
AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (DEBUG)
Log.i("BrazoRobotBT", "Turning on Bluetooth...");
mBluetoothAdapter.enable(); // Enciendo el Bluetooth
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (DEBUG)
Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
我在mDialog.show()
处遇到以下异常ctx
是我在构造函数中传递的活动上下文,我还尝试将MacActivity
传递到((活动)ctx)
到AlertDialog.Builder
,但我得到了相同的异常
该对话框要求用户启用蓝牙。我知道正确的方法是使用调用startActivityForResult()的内置方法,但我希望所有内容都在自定义类中,如果不是活动,我的类上就不能有onActivityResult(),这就是我采用这种方法的原因
为什么会这样?好的,我正在UI线程上创建对话框。我还尝试在onCreate()
方法中创建对话框,但仍然是一样的
03-06 21:06:20.320: E/WindowManager(31411): Activity com.roboticarm.andres.BrazoRobot has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4130de20 V.E..... R.....ID 0,0-495,244} that was originally added here
03-06 21:06:20.320: E/WindowManager(31411): android.view.WindowLeaked: Activity com.roboticarm.andres.BrazoRobot has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{4130de20 V.E..... R.....ID 0,0-495,244} that was originally added here
03-06 21:06:20.320: E/WindowManager(31411): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
03-06 21:06:20.320: E/WindowManager(31411): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
03-06 21:06:20.320: E/WindowManager(31411): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.Dialog.show(Dialog.java:281)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.AlertDialog$Builder.show(AlertDialog.java:951)
03-06 21:06:20.320: E/WindowManager(31411): at com.bluetoothutils.andres.BluetoothHelper.connect(BluetoothHelper.java:119)
03-06 21:06:20.320: E/WindowManager(31411): at com.roboticarm.andres.BrazoRobot.onResume(BrazoRobot.java:247)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.Activity.performResume(Activity.java:5217)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2862)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2901)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2364)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread.access$600(ActivityThread.java:153)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
03-06 21:06:20.320: E/WindowManager(31411): at android.os.Handler.dispatchMessage(Handler.java:99)
03-06 21:06:20.320: E/WindowManager(31411): at android.os.Looper.loop(Looper.java:137)
03-06 21:06:20.320: E/WindowManager(31411): at android.app.ActivityThread.main(ActivityThread.java:5204)
03-06 21:06:20.320: E/WindowManager(31411): at java.lang.reflect.Method.invokeNative(Native Method)
03-06 21:06:20.320: E/WindowManager(31411): at java.lang.reflect.Method.invoke(Method.java:511)
03-06 21:06:20.320: E/WindowManager(31411): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
03-06 21:06:20.320: E/WindowManager(31411): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
03-06 21:06:20.320: E/WindowManager(31411): at dalvik.system.NativeStart.main(Native Method)
但我总是得到完全相同的错误
编辑2(活动测试) 我曾尝试在“活动”中的onCreate()和onResume()中创建一个对话框,它是用以下简单代码完美创建的:
public class CustomDialog extends Activity{
private static final boolean DEBUG = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AlertDialog.Builder mDialog = new AlertDialog.Builder(this);
mDialog.setTitle(getString(R.string.BTRequestTitle));
mDialog.setMessage(getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
}
});
mDialog.setNegativeButton(getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
}
});
mDialog.show();
}
}
But, if I put this code inside my class method called from my Activity I get the exception.
编辑3(奇怪的事实) 这是我的connect()方法,当我从我的活动调用它时,我会在其中得到异常,对话框如下所示:
public void connect (){
// Compruebo que el dispositivo tenga Bluetooth
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Si no hay Bluetooth en el dispositivo muestro un dialogo alertando al usuario y salgo de la Activity
AlertDialog.Builder dialog = new AlertDialog.Builder(mActivity);
dialog.setTitle(ctx.getString(R.string.NoBTAlertTitle));
dialog.setMessage(ctx.getString(R.string.NoBTAlertText));
dialog.setPositiveButton(ctx.getString(R.string.Ok), new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
mActivity.finish(); // Cierro porque no existe un módulo Bluetooth
}
});
}
// Si el dispositivo tiene Bluetooth me conecto
else{
// Compruebo que el Bluetooth esté activado, sino pido al usuario que lo active
if (!mBluetoothAdapter.isEnabled()) {
//mActivity.startActivity(new Intent(mActivity, CustomDialog.class));
AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
mBluetoothAdapter.enable(); // Enciendo el Bluetooth
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
// Compruebo si el dispositivo no esta en los dispositivos emparejados (paired)
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop a travez de los dispositivos emparejados (paired)
for (BluetoothDevice device : pairedDevices) {
if(DEBUG) Log.i("BrazoRobotBT", "Name: " + device.getName() + " -- Address: " + device.getAddress());
// Si el dispositivo coincide con el que busco lo asigno
if(device.getName().equals(bluetoothName)){
mBluetoothDevice = device;
// Establezco una conexión Bluetooth para enviar datos
establishConnection();
break;
}
}
}
// Sino salgo, debe estar en los dispositivos emparejados
else{
mActivity.finish();
}
}
}
public void dialog(){
AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
并使用它:
mCustomClass.dialog(); // Dialog is shown, no exception
为了避免此错误,您应该在活动的onStop方法中调用
mDialog.disease()
原因:因为如果不正确处理对话框窗口,您无法简单地完成对话框所有者活动或跳转到新活动。为了避免此错误,您应该在活动的顶部方法中调用
mDialog.dismise()
原因:因为如果不正确处理对话框窗口,您无法简单地完成对话框所有者活动或跳转到新活动。休息一会儿后,我解决了它。又是我的错。问题基本上是我正在显示对话框,在它显示之前,我完成了活动:
public void connect (){
// Compruebo que el dispositivo tenga Bluetooth
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Si no hay Bluetooth en el dispositivo muestro un dialogo alertando al usuario y salgo de la Activity
AlertDialog.Builder dialog = new AlertDialog.Builder(mActivity);
dialog.setTitle(ctx.getString(R.string.NoBTAlertTitle));
dialog.setMessage(ctx.getString(R.string.NoBTAlertText));
dialog.setPositiveButton(ctx.getString(R.string.Ok), new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
mActivity.finish(); // Cierro porque no existe un módulo Bluetooth
}
});
}
// Si el dispositivo tiene Bluetooth me conecto
else{
// Compruebo que el Bluetooth esté activado, sino pido al usuario que lo active
if (!mBluetoothAdapter.isEnabled()) {
//mActivity.startActivity(new Intent(mActivity, CustomDialog.class));
AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
mBluetoothAdapter.enable(); // Enciendo el Bluetooth
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
// Compruebo si el dispositivo no esta en los dispositivos emparejados (paired)
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop a travez de los dispositivos emparejados (paired)
for (BluetoothDevice device : pairedDevices) {
if(DEBUG) Log.i("BrazoRobotBT", "Name: " + device.getName() + " -- Address: " + device.getAddress());
// Si el dispositivo coincide con el que busco lo asigno
if(device.getName().equals(bluetoothName)){
mBluetoothDevice = device;
// Establezco una conexión Bluetooth para enviar datos
establishConnection();
break;
}
}
}
// Sino salgo, debe estar en los dispositivos emparejados
else{
mActivity.finish();
}
}
}
public void connect(){
//蓝牙技术
mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter==null){
//在对话警报和日常活动中,不需要进行任何处理
AlertDialog.Builder dialog=新建AlertDialog.Builder(MacActivity);
setTitle(ctx.getString(R.string.NoBTAlertTitle));
setMessage(ctx.getString(R.string.NoBTAlertText));
setPositiveButton(ctx.getString(R.string.Ok),新的OnClickListener(){
@凌驾
public void onClick(DialogInterface dialog,int which){
mActivity.finish();//不存在módulo蓝牙
}
});
}
//这是我的第一次约会
否则{
//蓝牙技术是一种有效的技术,中国的蓝牙技术是一种有效的技术
如果(!mBluetoothAdapter.isEnabled()){
//startActivity(新意图(mActivity,CustomDialog.class));
AlertDialog.Builder mDialog=新建AlertDialog.Builder(ctx);
setTitle(ctx.getString(R.string.BTRequestTitle));
setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes),新的OnClickListener(){
@凌驾
public void onClick(DialogInterface dialog,int which){
if(DEBUG)Log.i(“BrazoRobotBT”,“打开蓝牙…”);
mBluetoothAdapter.enable();//Enciendo el蓝牙
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No),新的OnClickListener(){
@凌驾
public void onClick(DialogInterface dialog,int which){
if(DEBUG)Log.i(“BrazoRobotBT”,“Exit”);
mActivity.finish();
}
});
mDialog.show();
}
//无需对设备进行处理的压缩机(成对)
设置pairedDevices=mBluetoothAdapter.getBondedDevices();
如果(pairedDevices.size()>0){
//循环一次处理垃圾(成对)
用于(蓝牙设备:pairedDevices){
if(DEBUG)Log.i(“BrazoRobotBT”,“Name:+device.getName()+”--Address:+device.getAddress());
//这是一个垃圾处理站
if(device.getName().equals(bluetoothName)){
mBluetoothDevice=设备;
//环境数据公司
建立连接();
打破
}
}
}
//中国-萨尔戈(Sino-salgo)是一家大型企业
否则{
mActivity.finish();
}
}
}
我在`mDialog.show()')上显示对话框,但在按下“确定”按钮之前,蓝牙仍然未启用,因此没有配对的设备,因此我完成了活动,但对话框仍在绘制中,因此我得到了异常。愚蠢的错误我知道,有时候我应该休息一下
因此,“connect()”方法现在是:
public void connect (){
if(DEBUG) Log.i("BrazoRobotBT", "connect()...");
// Compruebo que el dispositivo tenga Bluetooth
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Si no hay Bluetooth en el dispositivo muestro un dialogo alertando al usuario y salgo de la Activity
AlertDialog.Builder dialog = new AlertDialog.Builder(mActivity);
dialog.setTitle(ctx.getString(R.string.NoBTAlertTitle));
dialog.setMessage(ctx.getString(R.string.NoBTAlertText));
dialog.setPositiveButton(ctx.getString(R.string.Ok), new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "No bluetooth on device");
mActivity.finish(); // Cierro porque no existe un módulo Bluetooth
}
});
}
// Si el dispositivo tiene Bluetooth me conecto
else{
// Compruebo que el Bluetooth esté activado, sino pido al usuario que lo active
if (!mBluetoothAdapter.isEnabled()) {
final AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
mBluetoothAdapter.enable(); // Enciendo el Bluetooth
// Espero a que encienda el Bluetooth
while(!mBluetoothAdapter.isEnabled());
// Compruebo si el dispositivo no esta en los dispositivos emparejados (paired)
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop a travez de los dispositivos emparejados (paired)
for (BluetoothDevice device : pairedDevices) {
if(DEBUG) Log.i("BrazoRobotBT", "Name: " + device.getName() + " -- Address: " + device.getAddress());
// Si el dispositivo coincide con el que busco lo asigno
if(device.getName().equals(bluetoothName)){
mBluetoothDevice = device;
// Establezco una conexión Bluetooth para enviar datos
establishConnection();
break;
}
}
}
// Sino salgo, debe estar en los dispositivos emparejados
else{
if(DEBUG) Log.i("BrazoRobotBT", "Finish Activity not in paired devices");
mBluetoothAdapter.disable();
mActivity.finish();
}
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
}
}
公共空间
public void connect (){
if(DEBUG) Log.i("BrazoRobotBT", "connect()...");
// Compruebo que el dispositivo tenga Bluetooth
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Si no hay Bluetooth en el dispositivo muestro un dialogo alertando al usuario y salgo de la Activity
AlertDialog.Builder dialog = new AlertDialog.Builder(mActivity);
dialog.setTitle(ctx.getString(R.string.NoBTAlertTitle));
dialog.setMessage(ctx.getString(R.string.NoBTAlertText));
dialog.setPositiveButton(ctx.getString(R.string.Ok), new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "No bluetooth on device");
mActivity.finish(); // Cierro porque no existe un módulo Bluetooth
}
});
}
// Si el dispositivo tiene Bluetooth me conecto
else{
// Compruebo que el Bluetooth esté activado, sino pido al usuario que lo active
if (!mBluetoothAdapter.isEnabled()) {
final AlertDialog.Builder mDialog = new AlertDialog.Builder(ctx);
mDialog.setTitle(ctx.getString(R.string.BTRequestTitle));
mDialog.setMessage(ctx.getString(R.string.BTRequestSummary));
mDialog.setPositiveButton(ctx.getString(R.string.Yes), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Turning on Bluetooth...");
mBluetoothAdapter.enable(); // Enciendo el Bluetooth
// Espero a que encienda el Bluetooth
while(!mBluetoothAdapter.isEnabled());
// Compruebo si el dispositivo no esta en los dispositivos emparejados (paired)
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop a travez de los dispositivos emparejados (paired)
for (BluetoothDevice device : pairedDevices) {
if(DEBUG) Log.i("BrazoRobotBT", "Name: " + device.getName() + " -- Address: " + device.getAddress());
// Si el dispositivo coincide con el que busco lo asigno
if(device.getName().equals(bluetoothName)){
mBluetoothDevice = device;
// Establezco una conexión Bluetooth para enviar datos
establishConnection();
break;
}
}
}
// Sino salgo, debe estar en los dispositivos emparejados
else{
if(DEBUG) Log.i("BrazoRobotBT", "Finish Activity not in paired devices");
mBluetoothAdapter.disable();
mActivity.finish();
}
}
});
mDialog.setNegativeButton(ctx.getString(R.string.No), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(DEBUG) Log.i("BrazoRobotBT", "Exit");
mActivity.finish();
}
});
mDialog.show();
}
}
}