Android:等待来自对话框的用户输入?

ab1*_*b11 37 android modal-dialog

我想实现一个显示对话框的方法,等待对话框解除,然后根据对话框内容返回结果.这可能吗?

public String getUserInput()
{
    //do something to show dialog
    String input = //get input from dialog
    return input;
}
Run Code Online (Sandbox Code Playgroud)

我实际上是在尝试实现一个具有方法"public String getUserInput()"的接口,其中必须通过对话框检索返回的String.这很容易在java中完成,在android中似乎不可能?

编辑:根据评论中的要求发布一些示例代码

getInput()必须从后台线程调用(我从AsynchTask中调用它).getInput()显示一个对话框并调用wait.在对话框上按下确定按钮时,对话框在成员变量中设置用户输入并调用notify.调用notify时,getInput()继续并返回成员变量.

String m_Input;

public synchronized String getInput()
{
    runOnUiThread(new Runnable() 
    {
        @Override
        public void run() 
        {
            AlertDialog.Builder alert = new AlertDialog.Builder(context);
            //customize alert dialog to allow desired input
            alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton)
            {
                          m_Input = alert.getCustomInput();
                          notify();
            }
        });
        alert.show();   
        }
    });

    try 
    {
         wait();
    } 
    catch (InterruptedException e) 
    {
    }

    return m_Input;
}
Run Code Online (Sandbox Code Playgroud)

Com*_*are 32

这可能吗?

没有.在Android中没有阻止UI模型.一切都是异步的.

UPDATE

在回答您对问题本身的一些评论时,您无法从后台线程显示UI.正如我在这个答案中所写,Android中没有阻止UI模型.只需将代码放在您希望在接受对话框时执行的对话框的按钮处理程序中,例如在此示例项目中.

  • 也许是有人不想听的答案?我曾经发生了几次. (3认同)
  • 您无法直接从后台线程显示UI,但您可以从后台线程询问UI线程是否为您显示它. (2认同)
  • 除非事件驱动模型过于令人头疼,否则我不会推荐它,或者除非处理大量遗留代码,特别是遗留代码最小化移植以构建为jni库. (2认同)

Chr*_*ton 12

正确的方法是事件驱动的程序模型,即"不要打电话给我们,我们会打电话给你".

在简单的控制台模式编程中,您的代码倾向于调用阻塞输入函数,这些函数在您获得值之前不会返回.

许多gui编程环境的工作方式不同 - 您的代码通常不会运行,而是在发生可能感兴趣的事情时由操作系统/窗口管理器调用.你做了一些事情以回应这个并立即返回 - 如果你不这样做,你不能得到任何其他通知,因为操作系统在你返回之前无法与你联系.(与win32相比,就好像消息循环是由Android实现的,你只能编写消息循环使用事件调用的其余代码 - 如果你没有及时返回,消息循环会挂起)

因此,您需要重新考虑您的程序流概念.不要将待办事项列表写为一系列简单的陈述,而应将其视为一系列依赖于彼此和输入的动作.记住您在状态变量中当前正在执行的操作.当您通过用户输入等事件调用时,查看该事件是否意味着现在可以继续执行下一步,如果是,则更新状态变量,然后立即返回操作系统以便能够接收下一个事件.如果事件不是您所需要的,那么只需返回而不更新您的状态.

如果这个模型不适合你,你可以做的是编写程序逻辑的后台线程,它使用阻塞输入像控制台模式应用程序一样运行.但是你的输入函数实际上只是等待一个标志或某些东西被通知输入可用.然后在Android传递事件的UI线程上,更新标志并立即返回.后台线程看到标志已更改以指示已提供数据,并继续执行.(像Android终端模拟器这样的东西把它带到了一个极端,其中后台组件实际上是另一个进程 - 一个控制台模式linux,它使用可能阻塞来自管道的I/O来获取它的输入.


ab1*_*b11 11

感谢所有的反馈,我能够使用后台线程以及wait()和notify()来解决这个问题.我认识到这不是给定范例的最佳想法,但有必要符合我正在使用的图书馆.

  • 体验过nodejs和python后,不得不说android并不复杂……它是复杂的 (4认同)

小智 6

到目前为止,我很难理解上面提供的所有解决方案,所以我找到了自己的解决方案。

我将应在用户输入确定后执行的代码包装在可运行程序中,如下所示:

    Runnable rOpenFile = new Runnable() {
        @Override
        public void run() {
            .... code to perform
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后,在其正下方,我将可运行函数的名称传递给用户对话框方法。

    userInput("Open File", rOpenFile);
Run Code Online (Sandbox Code Playgroud)

userInput方法基于如上所述的alertDialog构建器。当用户输入确定时,它将启动预期的可运行状态。

private void userInput(String sTitle, final Runnable func) {
    AlertDialog.Builder aBuilder = new AlertDialog.Builder(this);

    aBuilder.setTitle(sTitle);
    final EditText input = new EditText(this);
    input.setInputType(InputType.TYPE_CLASS_TEXT);
    aBuilder.setView(input);

    bDialogDone = false;

    aBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            final String sText = input.getText().toString();
            sEingabe = sText;
            func.run();
        }
    });
    aBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
            sEingabe = "";
        }
    });

    aBuilder.show();
}
Run Code Online (Sandbox Code Playgroud)