对话框/ AlertDialogs:如何在对话框启动时“阻止执行”(.NET样式)


73

来自.NET环境,我现在想了解Dialogs如何在Android中工作。

在.NET中,调用时MessageBox.Show(...)会创建并显示一个弹出对话框。在对Show的调用中,我可以指定在弹出窗口中应该使用哪些按钮,例如:

DialogResult myDialogResult = MessageBox.Show("My text here", "My caption here", MessageBoxButtons.YesNoCancel);

如您所见,当在弹出窗口中按下按钮时,对Show的调用将返回DialogResult,通知我单击了哪个按钮。请注意,在.NET中,执行将在Show(...)对它进行调用的行处暂停,因此在按下按钮时它可以返回值。

如果我在上面的示例中按“否”,则myDialogResult将等于

myDialogResult == DialogResult.No

由于我发现使用/创建弹出窗口的.NET方法非常简单直观,因此我也希望在Android中使用这种创建弹出窗口的方法。

因此,问题是,是否有人知道如何像一样“暂停执行” MessageBox.Show,然后每当按下Button(然后对话框消失)时返回一个值?

编辑1

要更清楚一点:

我需要暂停执行并等待,直到用户选择了一个按钮以单击弹出窗口。调用后显示对话框的代码取决于在对话框中单击的按钮。

这就是为什么我不能使用Erich和Alex的建议的原因,因为按照下面的建议在onClick方法中编写代码是行不通的。原因是我无法继续执行“正常执行”。让我举个例子:

让我举个例子:

int nextStep = 0; // this variable will not be reached from within the onClick-methods

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 1; // *** COMPILER ERROR!! ***
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 2; // *** COMPILER ERROR!! ***
            }
        })
        .create().show();

if (nextStep == 1)
{
    // then do some damage
}
else if (nextStep == 2
    // dont do damage

如果我希望执行依赖于弹出窗口中的选择,那么我将不得不以某种方式使nextSteponClick方法中的“正常执行”(在本例中为)中的所有变量可用,这对我来说听起来像是“地狱”。

编辑2

另一个明显的示例是弹出窗口,询问“您是否要继续”,并带有选项“是”“否”

如果用户按下“是”,则应中止整个方法,否则应继续执行。您如何很好地解决呢?


看看fupsduck的新增段落是否有帮助
fupsduck 2010年

4
或者,您也可以将“对话框”设计为与对话框具有相同外观的活动。如果对话框具有很多逻辑,则采用这种方式可能会更容易实现。
Erich Douglass 2010年

2
关于警报对话框,.NET很棒,Android很烂。在某些情况下,我需要MessageBox来帮助调试。在.NET中,直到关闭MessageBox,MessageBox之后的代码才会运行。但是,在Android中,它不起作用。我认为在Windows中,显示模式对话框时会有另一个消息循环。在Android中,我认为窗口和对话框使用相同的消息循环。
2014年

相反,具有If (nextStep == 1) { }If (nextStep == 2) { },你需要有一个空隙叫,说,public void nextStep1public void nextStep2当用户点击某个按钮被调用。如果他们共享代码后缀,则可以使另一个空白,使他们每个人都在使用其中的其余代码调用后缀。
Cullub

我认为Android小伙子@Romain Guy只是说过:“您不应该设计外观漂亮的程序来做出选择并根据选择采取行动。” 如果有一系列相似的选择并相互关联,则在Android中可能需要100倍的代码行。我不知道将其添加到Android库有什么困难或副作用,但是我认为从他们那里很难。
rml 2015年

Answers:


49

泰德(Ted),您实际上并不想这样做:)最大的原因是,如果在显示Dialog时阻塞UI线程,则会阻塞负责绘制和处理Dialog事件的线程。这意味着您的对话框将无响应。如果用户花费超过几秒钟的时间单击对话框,您还将导致ANR。

Erich的答案正是您所需要的。我知道这不是您想要的,但这没关系。我们设计Android的目的是防止开发人员编写同步对话框,因此您实际上没有太多选择。


20
这是一团糟,因为您正在以一种与Android无关的方式来构建代码。只是做不同的事情。如果您拒绝这样做,那就是您的问题。例如,不是使用3个阻止对话框(顺便说一句,我发现这是一个糟糕而懒惰的UI),而是为什么没有活动,为什么所有问题都只有您确认您开始执行您的应用程序,才为什么有活动?应该在做。您问了一个问题,我们已经回答了,到目前为止您唯一要说的就是您不喜欢我们的回答。抱歉,他们不会改变。
罗曼·盖伊

60
不要再告诉人们他们不应该尝试去做自己想做的事情。如果有什么“可怕而懒惰的”,那就(答案)就可以了。当然,您可以在Android中创建模式对话框,只需要编写更多代码即可。从用户的角度来看,该UI没什么不好的。许多UI框架(不仅是Windows)都支持此概念。如果有一个简单的单行答案,则发贴者可能不需要问这个问题。如果您不想做回答他的问题的工作,那就别管它了。
Nate

6
@radhoo因为这样的小细节,所以为什么我会看到如此恐怖的移动应用程序(例如,看起来像是由Java家伙设计的iOS应用程序和由C ++人员设计的Android畸变)(例如)。您必须学习和理解您正在使用的平台,不一定要通过自己的想法强迫自己前进。每个平台都有其优点和缺点,无论是否喜欢。Android中的生命周期模型就是以此方式设计,处理它并学习围绕它构建的。
Martin Marconcini

8
@rml我在Android框架团队中工作,我们专门设计了框架,使其不具有阻止当前执行线程的模式对话框。我知道该怎么做,但这不是我们为Android选择的模型。
罗曼·盖伊

35
请注意OP当然不想真正停止UI线程,只是想阻塞用户工作流。由于这是一个有效且常见的用例(因为用户几乎从未与它们的小工具执行多次并行交互,并且系统通常需要等待它们),因此很自然地期望一些琐碎的模式对话框API能与“单线程用户”现实无缝地匹配。如果做起来不容易,这是可以理解的。但是,如果Android团队能够提出一种巧妙的方法来使其像问题中所示的那样微不足道,那么它只会对我们所有人有所帮助。谢谢!
Sz。

21

在Android中,结构与.NET不同:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // Handle Ok
           }
       })
       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // Handle Cancel
           }
       })
       .create();

将为您提供带有两个按钮的对话框,并通过回调处理按钮单击。您可能可以编写一些代码来使语法更类似于.NET,但是对话框的生命周期与缠绕在一起Activity,因此,最后,麻烦可能超过其价值。其他对话框参考在这里


4
因此,Android中不存在“模态”对话框之类的东西吗?你不能当真
ComeIn

20

丹尼尔答案的简化版。此功能在警报对话框中从用户获得是或否,但可以轻松修改以获取其他输入。

private boolean mResult;
public boolean getYesNoWithExecutionStop(String title, String message, Context context) {
    // make a handler that throws a runtime exception when a message is received
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message mesg) {
            throw new RuntimeException();
        } 
    };

    // make a text input dialog and show it
    AlertDialog.Builder alert = new AlertDialog.Builder(context);
    alert.setTitle(title);
    alert.setMessage(message);
    alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            mResult = true;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            mResult = false;
            handler.sendMessage(handler.obtainMessage());
        }
    });
    alert.show();

    // loop till a runtime exception is triggered.
    try { Looper.loop(); }
    catch(RuntimeException e2) {}

    return mResult;
}

谢谢,这个很好用。我更喜欢Erich的方式,但它不会阻止执行(我经常使用的解决方案)。至少您的方法按问题预期的那样工作,并且答案很有趣。
Solostaran14 2012年

这是对该问题最相关的答案,并且是一个有创意的解决方案,但是它有时会因以下致命错误而失败:A / libc:致命信号11(SIGSEGV),代码1,在tid 274中出现错误addr 0x1 ...是有人对此有解决方案吗?
rml 2015年

我想说的是,这也适用于HTTP请求。我刚刚通过Volley完成了HTTP请求,该想法是在执行HTTP请求时代码必须继续(在主要威胁下)。但是,出色的服务,为什么不让我们决定是程序员,还是要坐无休止的呼叫深度级别来进行体操,还是要进行自己的线程化?您上面的出色示例无需添加单个螺钉或螺母即可工作。现在,我有模式HTTP调用了。尽管(!),我还是通过普通线程整理了AlertDialog。您可以在哪里与其他人分享
David Svarrer

11

在Android中,对话框是异步的,因此您将不得不对代码进行一些不同的构造。

因此,在C#中,您的逻辑在伪代码中运行了以下内容:

void doSomeStuff() {
    int result = showDialog("Pick Yes or No");

    if (result == YES) {
        //do stuff for yes
    }
    else if (result == NO) {
        //do stuff for no
    }

    //finish off here
}

对于Android,它将必须不那么整洁。这样想吧。您将拥有一个OnClickListener这样的:

public void onClick(DialogInterface dialog, int whichButton) {
   if (whichButton == BUTTON_POSITIVE) {
      doOptionYes();
   }
   else if (whichButton == BUTTON_NEGATIVE) {
      doOptionNo();
   }
}

然后由以下方法支持:

void doOptionYes() {
    //do stuff for yes
    endThings();
}

void doOptionNo() {
    //do stuff for no
    endThings();
}

void endThings() {
    //clean up here
}

所以现在一种方法是四种。它可能看起来不那么整洁,但是恐怕就是这样。


1
谢谢戴夫!是的,这就是我从所有这些答案中学到的东西。不幸的是我不得不说...再次谢谢=)
Ted

3
我发现这有点令人沮丧,因为如果一切正常,有时我的执行流程会绕过对话框。如果有问题,我会问“继续前进”或“忘记它”。所以现在我有2种获取持续代码的方法。所以我必须将其放入自己的方法中。所以我必须重新做所有重新进入对话框的设置。糟糕的设计恕我直言。
2012年

9
PasswordDialog dlg = new PasswordDialog(this);

if(dlg.showDialog() == DialogResult.OK)

{

    //blabla, anything your self

}


public class PasswordDialog extends Dialog
{
    int dialogResult;
    Handler mHandler ;

    public PasswordDialog(Activity context, String mailName, boolean retry)
    {

        super(context);
        setOwnerActivity(context);
        onCreate();
        TextView promptLbl = (TextView) findViewById(R.id.promptLbl);
        promptLbl.setText("Input password/n" + mailName);
    }
    public int getDialogResult()
    {
        return dialogResult;
    }
    public void setDialogResult(int dialogResult)
    {
        this.dialogResult = dialogResult;
    }
    /** Called when the activity is first created. */

    public void onCreate() {
        setContentView(R.layout.password_dialog);
        findViewById(R.id.cancelBtn).setOnClickListener(new android.view.View.OnClickListener() {

            @Override
            public void onClick(View paramView)
            {
                endDialog(DialogResult.CANCEL);
            }
            });
        findViewById(R.id.okBtn).setOnClickListener(new android.view.View.OnClickListener() {

            @Override
            public void onClick(View paramView)
            {
                endDialog(DialogResult.OK);
            }
            });
        }

    public void endDialog(int result)
    {
        dismiss();
        setDialogResult(result);
        Message m = mHandler.obtainMessage();
        mHandler.sendMessage(m);
    }

    public int showDialog()
    {
        mHandler = new Handler() {
            @Override
              public void handleMessage(Message mesg) {
                  // process incoming messages here
                //super.handleMessage(msg);
                throw new RuntimeException();
              }
          };
        super.show();
        try {
            Looper.getMainLooper().loop();
        }
        catch(RuntimeException e2)
        {
        }
        return dialogResult;
    }

}

5

为了优化内存和性能,Android中的对话框是异步的(因此也要对其进行管理)。来自Windows世界,您习惯于模式对话框。Android对话是模态的,但执行时更像是非模态的。显示对话框后执行不会停止。

我所见过的关于Dialogs的最佳描述是在“ Pro Android”中http://www.apress.com/book/view/1430215968

这不是一个完美的解释,但是它应该可以帮助您围绕Windows和Android中的Dialogs之间的差异进行思考。在Windows中,您想执行A,向对话框提问,然后执行B或C。在android设计A中,对话框的OnClickListener的onClick()中包含B和C所需的所有代码。然后执行A并启动对话框。您已经完成A!当用户单击按钮B或C将被执行。

Windows
-------
A code
launch dialog
user picks B or C
B or C code
done!

Android
-------
OnClick for B code (does not get executed yet)
OnClick for C code (does not get executed yet)
A code
launch dialog
done!
user picks B or C

1
如果此线程中没有其他内容,那么您的情况就是如此。但是您那里总是还有其他东西。因此,您必须防止发生其他事情,或处理可能改变状态并导致B或C功能无法正常工作的数十万种情况。Android方式使其变得过于复杂。
rml

它实际上并没有什么复杂,只是有所不同。
Cullub 2014年

2
如果有很多类似的问题要依次回答,并且每个选择都会影响以后的过程,那么使用android中使用的不间断对话框会很麻烦,但是使用Windows对话框会容易得多。绝对不是一样。
rml 2015年

5

不幸的是,Android和iOS的开发人员认为它们足够强大和聪明,可以拒绝“模态对话框”的概念(该模型已经在市场上销售了很多年,之前从未有人打扰过)。我相信可以解决Android问题-因为您可以使用Runnable类从非UI线程显示对话框,所以应该有一种方法可以在该线程(非UI)中等待对话框完成。

编辑:这是我的解决方案,效果很好:

    int pressedButtonID;
    private final Semaphore dialogSemaphore = new Semaphore(0, true);
    final Runnable mMyDialog = new Runnable()
    {
        public void run()
        {
            AlertDialog errorDialog = new AlertDialog.Builder( [your activity object here] ).create();
            errorDialog.setMessage("My dialog!");
            errorDialog.setButton("My Button1", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    pressedButtonID = MY_BUTTON_ID1;
                    dialogSemaphore.release();
                    }
                });
            errorDialog.setButton2("My Button2", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    pressedButtonID = MY_BUTTON_ID2;
                    dialogSemaphore.release();
                    }
                });
            errorDialog.setCancelable(false);
            errorDialog.show();
        }
    };

    public int ShowMyModalDialog()  //should be called from non-UI thread
    {
        pressedButtonID = MY_BUTTON_INVALID_ID;
        runOnUiThread(mMyDialog);
        try
        {
            dialogSemaphore.acquire();
        }
        catch (InterruptedException e)
        {
        }
        return pressedButtonID;
    }

4

泰德(Ted),您可能已经发现,很不幸,您无法在Android上做到这一点。对话框是模态的,但是是异步的,它肯定会破坏您要尝试建立的顺序,就像在.NET(或Windows)上一样。您将不得不扭曲您的代码并破坏一些逻辑,这些逻辑根据您的示例将非常容易遵循。

另一个非常简单的示例是将数据保存在文件中,只是发现该文件已经存在并且要求覆盖它。无需显示对话框并让if语句对结果起作用(是/否),您将必须使用回调(在Java中称为侦听器)并将逻辑拆分为多个函数。

在Windows上,当显示对话框时,消息泵将在后台继续(仅当前正在处理的消息处于保留状态),并且工作正常。例如,这使用户可以在显示对话框时移动您的应用程序并重新绘制。WinMo支持同步模式对话框,BlackBerry也支持,但Android不支持。


15
微软在20年前实施了模式对话框,没有任何阻塞,这使得代码非常流畅且易于阅读(任何Windows开发人员都可以证明),方法是使用第二个消息泵来处理对话框交互,同时将非对话框消息分发给该应用程序,在显示对话框时不会被阻止。Android没有这种实现,因此您需要拆分代码。Android设计师更愿意告诉我们“这是我们的路还是高速公路”,而不是听他们的客户(开发人员)的需求
user545076 2011年

2

最干净,最简单的解决方案是使用您自己的侦听器界面,以便当用户单击ok按钮时,将使用返回值调用侦听器。此方法没有花哨或复杂的操作,并且遵守android原则。

定义您的侦听器接口,如下所示:

public interface EditListener
/* Used to get an integer return value from a dialog
 * 
 */
{
 void returnValue(int value); 
}

对于我的应用程序,我创建了一个EditValue类,该类使用AlertDialog并在我想编辑整数值时调用。注意如何将EditListener接口作为参数传递给此代码。当用户单击“确定”按钮时,该值将通过EditListener方法返回到您的调用代码:

public final class EditValue
/* Used to edit a value using an alert dialog
 * The edited value is returned via the returnValue method of the supplied EditListener             interface
 * Could be modified with different constructors to edit double/float etc
 */
{
 public EditValue(final Activity parent, int value, String title, String message,
                  final EditListener editListener)
 {AlertDialog.Builder alert= new AlertDialog.Builder(parent);
  if(title==null) title= message;
  else if(message==null) message= title;
  if(title!=null) alert.setTitle(title);
  if(message!=null) alert.setMessage(message);

  // Set an EditText view to get user input 
  final EditText input = new EditText(parent);
  input.setText(String.valueOf(value));
  input.setInputType(InputType.TYPE_CLASS_NUMBER);
  alert.setView(input);

  alert.setPositiveButton("OK",new DialogInterface.OnClickListener()
  {public void onClick(DialogInterface dialog, int which)
   {try
    {int newValue= Integer.valueOf(input.getText().toString());
     editListener.returnValue(newValue);
     dialog.dismiss();
    }catch(NumberFormatException err) { }
   }
  });

  alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
  {public void onClick(DialogInterface dialog, int which)
   {dialog.dismiss();
    }
  });

  alert.show();
 }
}

最后,当您使用EditValue时,需要声明您的EditListener,现在您可以访问返回值并执行您想做的事情:

 new EditValue(main,AnchorManager.anchorageLimit,
               main.res.getString(R.string.config_anchorage_limit),null,
               new EditListener()
 {public void returnValue(int value) {AnchorManager.anchorageLimit= value;}
  }
 );


1

我是Android / Java世界的新手,很惊讶地在这里发现模式对话框不起作用(除非我不明白我所读的内容)。由于目前出于某些非常晦涩的原因,我得到了一个带有ok按钮的“ ShowMessage”等效项,该按钮可以以非常模块化的方式在平板电脑上使用。

在我的TDialogs.java模块中:

class DialogMes 
{

  AlertDialog alertDialog ;
  private final Message NO_HANDLER = null;
  public DialogMes(Activity parent,String aTitle, String mes)
  {
    alertDialog = new AlertDialog.Builder(parent).create();
    alertDialog.setTitle(aTitle);    
    alertDialog.setMessage(mes) ;  
    alertDialog.setButton("OK",NO_HANDLER) ;    
    alertDialog.show() ; 
  } 
}

这是测试代码的一部分:

public class TestDialogsActivity extends Activity implements DlgConfirmEvent
{

   @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button btShowMessage = (Button) findViewById(R.id.btShowMessage);
    btShowMessage.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) 
      {
        DialogMes dlgMes = new DialogMes( TestDialogsActivity.this,"Message","life is good") ;                
      }  
    }); 

按照上面JohnnyBeGood建议的界面方法,我还实现了一个模态的“是/否”对话框,它也很好用。

更正:

我的答案与我误解的问题无关。由于某种原因,我将罗曼·盖伊(M. Romain Guy)的“您不想这样做”解释为对模态对话框的否定。我应该读过:“您不想这样做……”。

我道歉。


1

改写:

移动和桌面环境之间以及数年前和今天的应用程序开发方式之间存在根本差异:

a)移动设备需要节约能源。他们提供的部分价值。因此,您需要节省资源。线程是一种昂贵的资源。暂停线程的进度是对这种资源的不可接受的浪费。

b)如今,用户要求更高。为了帮助他们,我们认为应该拥有完整的工作CPU和尽可能少的能源消耗。它的应用程序并不仅仅存在于设备上,同时还有数量不详的其他应用程序正在运行,您的应用程序不一定是最紧迫的。

c)不能选择系统级锁定:移动设备在后台处理许多事件和服务,并且不正确,因为任何事件和服务都可以被应用程序锁定。

考虑一下您的“系统锁定”正在工作时用户接听电话的情况...

基于以上事实,对所提问题的答案为:

  • 有一种可行的方法来建立一个对话框,该对话框阻止主线程,直到用户做出响应为止?

不能。解决方法会使用户体验变得更糟,并且可能会犯错归咎于系统本身。这是不公平的,并会惩罚平台及其所有开发人员。

  • 有没有办法通过对话阻止整个系统?

否。平台上严禁这样做。任何应用程序都不会干扰系统或其他应用程序的运行。

  • 我需要重构我的应用程序,或者重新考虑我的编程方式以适合我在Android移动系统架构上的需求。

是。包括这方面。


这听起来不像是一个好的答案,更像是一个咆哮,请编辑或删除...
user1781290 2014年

0

您可以将onclick侦听器设置为按钮。对话对话框,然后执行您的操作。不需要停止任何事情

protected Dialog onCreateDialog(int id) {
  return new AlertDialog.Builder(this).setTitle(R.string.no_connection).setIcon(android.R.drawable.ic_dialog_alert).setView(textEntryView).setPositiveButton(R.string.exit, new DialogInterface.OnClickListener() 
{

   public void onClick(DialogInterface dialog, int whichButton) {

  // Here goes what you want to do
  }

})
}

致电-​​例如-showDialog(DIALOG_ERROR_PREF);

更多 http://developer.android.com/guide/topics/ui/dialogs.html


嘿,那不是我真正想要的。无论何时显示弹出窗口,都应在按下弹出窗口中的按钮之一之后再执行以下代码。按下按钮的值应返回给调用者,以便调用者可以决定要做什么...我将在上面更新我的问题。
Ted 2010年

2
由于它不是真正的.Net,我认为您必须适应。而且它也不是台式机。将您的事件分解为事件。您已执行一些操作来显示对话框。现在,用户通过按按钮做出反应。好吧-调用doDamage(); dontDoDamage()方法。并从那里继续
Alex Volovoy 2010年

0

只是回答您的问题...对不起,我迟到了9个月:D ...有一种“解决方法” 4这种问题。即

new AlertDialog.Builder(some_class.this).setTitle("bla").setMessage("bla bla").show();
wait();

只需添加等待();

然后他们在OnClickListener中使用notify()再次启动此类

@Override
    public void onClick(DialogInterface dialog, int item) {
        Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();
        **notify**();
        dialog.cancel();
    }

相同的解决方法在Android中进行了4次Toast和其他异步调用


谢谢=)如果我再次开始使用Android,请尝试一下。但是,我放弃了Android。至少现在。
泰德(Ted)2010年

嘿,我说我很抱歉:P遇到了同样的问题,想让人们知道解决方法。当然,这并不简单...我最终需要一个新线程和2个新的可运行对象,这些对象在同步后依此类推。上...如果有人需要完整的代码,这会有点恶魔般的问题...问:)它很大,我的意思是代码um oh hm
mc_fish 2010年

呵呵,这是我的信息=)我会记得,如果我再次进入Android开发=)
Ted

2
如果您使用此“替代方法”,并且您的用户在10秒钟内未回复,则会在您的应用中收到ANR错误。这行不通。
贾斯汀·布雷特弗勒2011年

0

在线程(而不是UI线程)中尝试以下操作:

final CountDownLatch latch = new CountDownLatch(1);
handler.post(new Runnable() {
  @Override
  public void run() {
    OnClickListener okListener = new OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
      latch.countDown();
    }
  };

  AlertDialog dialog = new AlertDialog.Builder(context).setTitle(title)
    .setMessage(msg).setPositiveButton("OK", okListener).create();
  dialog.show();
}
});
try {
  latch.await();
} catch (InterruptedException e) {
  e.printStackTrace();
}

0
UserSelect =null

AlertDialog.Builder builder = new Builder(ImonaAndroidApp.LoginScreen);
            builder.setMessage("you message");
            builder.setPositiveButton("OK", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = true ;

                }
            });

            builder.setNegativeButton("Cancel", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = false ;

                }
            });
           // in UI thread
        builder.show();             
        // wait until the user select
            while(UserSelect ==null);

您的最后一行是“ while(UserSelect == null);”。-那是杀手。您的手机将陷入无休止的循环,实际上将无缘无故地加热CPU并耗尽电池,并使整个手机变慢。
David Svarrer

0

我正在使用Xamarin.Android(MonoDroid),并且我有开发UI阻止确认框的要求。我不会与客户争执,因为我可以看到他们为什么要这样做的充分理由(此处有详细信息),因此我需要实现这一点。我在上面尝试了@Daniel和@MindSpiker,但是它们在MonoForAndroid上不起作用,当消息在线程之间发送时,应用程序崩溃了。我认为这与Xamarin映射有关。

我最终从UI线程创建了一个单独的线程,然后阻止该线程并等待用户响应,如下所示:

// (since the controllers code is shared cross-platforms)
protected void RunConfirmAction(Action runnableAction)
{
    if (runnableAction != null)
    {
        if (Core.Platform.IsAndroid)
        {
            var confirmThread = new Thread(() => runnableAction());
            confirmThread.Start();
        }
        else
        {
            runnableAction();
        }
    }
}

// The call to the logout method has now changed like this:
RunConfirmAction(Logout);

// the implemtation of the MessageBox waiting is like this:
public DialogResult MessageBoxShow(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
    if (_CurrentContext != null && _CurrentContext.Screen != null && MainForm.MainActivity != null)
    {
        Action<bool> callback = OnConfirmCallBack;
        _IsCurrentlyInConfirmProcess = true;
        Action messageBoxDelegate = () => MessageBox.Show(((Activity)MainForm.MainActivity), callback, message, caption, buttons);
        RunOnMainUiThread(messageBoxDelegate);
        while (_IsCurrentlyInConfirmProcess)
        {
            Thread.Sleep(1000);
        }               
    }
    else
    {
        LogHandler.LogError("Trying to display a Message box with no activity in the CurrentContext. Message was: " + message);
    }
    return _ConfirmBoxResult ? DialogResult.OK : DialogResult.No;

}

private void OnConfirmCallBack(bool confirmResult)
{
    _ConfirmBoxResult = confirmResult;
    _IsCurrentlyInConfirmProcess = false;
}

private bool _ConfirmBoxResult = false;
private bool _IsCurrentlyInConfirmProcess = false;

有关如何执行此操作的完整详细信息,请参见我的博客文章


0

让我向StackOverflow社区表示感谢,并与您分享一些美好的东西,在该示例中,我在Android代码中将上述示例用于HTTP调用,该示例现在变为MODAL,而不是通常的额外线程以及使用合并线程的复杂性有点奇怪的线程。(目前正在我们的应用程序中运行-2020年10月15日)

public JSONArray genericHttpModal(Context context, final String url, final JSONObject request) {

    this.url = url;    
    genericHttpRequestQueue = Volley.newRequestQueue(context);      
    class MyJsonReturn {
        JSONArray returnJsonArray;

        public void set(JSONArray i) {
            returnJsonArray = i;
        }

        public void set(String i) {
            try {
                returnJsonArray.put(0, i);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public JSONArray get() {
            return returnJsonArray;
        }
    }

    final MyJsonReturn mymy = new MyJsonReturn();

    // Positive Response / HTTP OK.
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            throw new RuntimeException();
        }
    };

    final Response.Listener responseListener = new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                mymy.set(new JSONArray(response));
            } catch (JSONException e) {
                mymy.set("[{\"JSONException:\"" + e.getMessage() + "\"}]");
            }
            handler.sendMessage(handler.obtainMessage());
        }
    };

    // Negative Response / HTTP NOT OK
    final Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            result = "fail";

            try {
                mymy.set(new JSONArray("[{\"JSONException:\"" + result + "\"}]"));
            } catch (JSONException e) {
                mymy.set("[{\"JSONException:\"" + e.getMessage() + "\"}]");
            }
            handler.sendMessage(handler.obtainMessage());
        }
    };


    final StringRequest httpRequest = new StringRequest(Request.Method.POST, URL_POINTER + url,
            responseListener,
            errorListener) {

        // Here the mRequestQueue handler will get the parameters for this request here.
        // Ref: /programming/33573803/how-to-send-a-post-request-using-volley-with-string-body#33578202
        // Ref: Multi Threaded solution 14 Oct 2020 (David Svarrer) : /programming/2028697/dialogs-alertdialogs-how-to-block-execution-while-dialog-is-up-net-style (This stackoverflow here)
        @Override
        protected java.util.Map<String, String> getParams() throws AuthFailureError {
            return jsonObjectToMap(request);
        }
    };
    httpRequest.setShouldCache(false); // Elijah: Could work on dropping the cache !!!
    genericHttpRequestQueue.add(httpRequest);    

    try {
        Looper.loop();
    } catch (RuntimeException re) {
    }
    return mymy.get();
}

-1

这是最简单的方法:

new AlertDialog.Builder(this).setTitle("title").setMessage("message").create().show();

是的,但是那并不能解决问题。我在想我想解决的问题,我的问题不见我的“ EDIT 1” =)问候
Ted 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.