Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:等待对话框中的用户输入?_Android_Modal Dialog - Fatal编程技术网

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

Android:等待对话框中的用户输入?,android,modal-dialog,Android,Modal Dialog,我想实现一个方法,它显示一个对话框,等待对话框关闭,然后根据对话框内容返回结果。这可能吗 public String getUserInput() { //do something to show dialog String input = //get input from dialog return input; } 实际上,我正在尝试实现一个接口,该接口具有方法“publicstringgetuserinput()”,其中必须通过对话框检索返回的字符串。这在java

我想实现一个方法,它显示一个对话框,等待对话框关闭,然后根据对话框内容返回结果。这可能吗

public String getUserInput()
{
    //do something to show dialog
    String input = //get input from dialog
    return input;
}
实际上,我正在尝试实现一个接口,该接口具有方法“publicstringgetuserinput()”,其中必须通过对话框检索返回的字符串。这在java中很容易做到,在android中似乎不可能做到

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

getInput()
必须从后台线程调用(我从异步任务调用它)。getInput()显示一个对话框并调用wait。当按下对话框上的ok按钮时,对话框将在成员变量中设置用户输入并调用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;
}

这样就行了

/**
 *
 */

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

/**
 * @author 
 */
public class TextEntryActivity extends Activity {
    private EditText et;

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_text_entry);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
        // title
        try {
            String s = getIntent().getExtras().getString("title");
            if (s.length() > 0) {
                this.setTitle(s);
            }
        } catch (Exception e) {
        }
        // value

        try {
            et = ((EditText) findViewById(R.id.txtValue));
            et.setText(getIntent().getExtras().getString("value"));
        } catch (Exception e) {
        }
        // button
        ((Button) findViewById(R.id.btnDone)).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                executeDone();
            }
        });
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onBackPressed()
     */
    @Override
    public void onBackPressed() {
        executeDone();
        super.onBackPressed();
    }

    /**
     *
     */
    private void executeDone() {
        Intent resultIntent = new Intent();
        resultIntent.putExtra("value", TextEntryActivity.this.et.getText().toString());
        setResult(Activity.RESULT_OK, resultIntent);
        finish();
    }


}
这次发射是:

public void launchPreferedNameEdit() {
    Intent foo = new Intent(this, TextEntryActivity.class);
    foo.putExtra("value", objItem.getPreferedNickname());
    this.startActivityForResult(foo, EDIT_PREFERED_NAME);
}
通过使用

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case EDIT_PREFERED_NAME:
            try {
                String value = data.getStringExtra("value");
                if (value != null && value.length() > 0) {

                }
            } catch (Exception e) {
            }
            break;
        default:
            break;
    }
}
这可能吗

public String getUserInput()
{
    //do something to show dialog
    String input = //get input from dialog
    return input;
}
没有。Android中没有阻塞UI模型。一切都是异步的

更新


对于您对问题本身的一些评论,您不能从后台线程显示UI。正如我在回答中所写的,Android中没有阻塞UI模型。只需将代码放入对话框的按钮处理程序中,您希望在对话框被接受时执行该按钮处理程序,例如。

正确的方法是使用事件驱动的程序模型,即“不要呼叫我们,我们将呼叫您”

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

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

因此,您需要重新思考您的程序流概念。与其把一个待办事项列表写成一系列简单的语句,不如把它看作是一系列相互依赖、依赖于输入的动作。记住当前在状态变量中执行的操作。当您被一个事件(如用户输入)调用时,请查看该事件是否意味着现在可以进入下一步,如果可以,请在立即返回操作系统之前更新状态变量,以便能够接收下一个事件。如果事件不是您需要的,那么只需返回而不更新您的状态


如果这个模型不适合您,那么您可以编写一个程序逻辑的后台线程,它使用阻塞输入运行起来就像控制台模式的应用程序。但您的输入函数实际上只是等待一个标志或某个东西通知您输入可用。然后在Android交付事件的UI线程上,更新标志并立即返回。后台线程看到标志已更改以指示已提供数据,并继续执行。(类似于android终端仿真器的东西将这一点发挥到了极致,后台组件实际上是另一个进程——控制台模式的linux进程,它使用来自管道的潜在阻塞I/O来获取输入。java组件接受android UI事件并将字符填充到stdin管道中,然后将它们从stdout管道中拉出感谢所有的反馈,我使用了一个后台线程以及wait()和notify()解决了这个问题。我认识到对于给定的范例来说,这并不是最好的想法,但有必要遵守我正在使用的库。

案例:在偏好更改侦听器事件之后,我的数据已准备好进行处理,我需要添加一个从用户处查询的字符串。当选项菜单打开时,似乎不可能弹出警报对话框…所以我不得不等待。我将半完整的对象扔到工作流中的下一个活动中,并将其onResume()设置为检查其占位符是否正确!在这种情况下,我弹出对话框并在对话框“*的按钮处理程序中完成对象“*”


由于这是我的第一篇帖子,我不能投票支持上面给出的正确答案,但我想让其他人省去时间,省去一些不太正确的解决方案。对话框就是这个地方。

您可以从状态机的角度考虑,如果您最初需要首次用户输入,您可以设置一个标记来标记“需要用户输入”或其他任何内容。然后,在处理一个事件时,检查该标志,如果设置了,则启动一个对话框作为该事件的唯一操作,并取消设置该标志。然后,在处理用户输入后,您可以从对话框事件处理程序调用通常用于不需要对话框的情况的代码。

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

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

    Runnable rOpenFile = new Runnable() {
        @Override
        public void run() {
            .... code to perform
        }
    }
然后在它的正下方,我将可运行函数的名称传递给用户对话框方法

    userInput("Open File", rOpenFile);
userInput方法基于上述alertDialog builder。当用户输入确定后,它将启动预期的可运行程序

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();
}

我刚才做了一个对话,供你参考

它将显示并等待,然后关闭

我部署了Java wait和notify来实现它,这个函数可以直接复制和运行

private final Object lock = new Lock();
private static final class Lock {}
private void showWaitDialog(final String message, final int time_to_wait) { //ms
    if(this.isFinishing()) return;
    final String TTAG = "[showWaitDialog]";
    Log.d(TTAG, "dialog going to show");
    final ProgressDialog waitProgress = ProgressDialog.show(this, "WARNING", message, true);
    waitProgress.setCancelable(false);
    waitProgress.setOnShowListener(new DialogInterface.OnShowListener() { //callback got the asynchronous
        @Override
        public void onShow(DialogInterface dialog) {
            Log.d(TTAG, "dialog showed");
            synchronized (lock) {
                try {
                    Log.d(TTAG, "main thread going to wait");
                    lock.wait();
                } catch (InterruptedException e) {
                    Log.e(TTAG, e.toString());
                    Log.e(TTAG, "main thread going ahead");
                }
            }
        }
    });
    new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (lock) {
                try {
                    Thread.sleep(time_to_wait);
                } catch (Exception e) {
                    Log.d(TTAG, e.toString());
                }
                lock.notifyAll();
                Log.d(TTAG, "dialog notified");
                waitProgress.dismiss();
            }
        }
    }).start();
}

您不能在UI线程上调用的方法中等待用户。因此,您必须切换到程序流的事件驱动模型,或者从后台线程调用它,该线程可以等待onWhatever()方法