Android: подождите от ввода пользователем из диалогового окна?

Я хотел бы реализовать метод, который отображает диалог, ждет, пока диалог не будет отклонен, а затем вернет результат в зависимости от содержимого диалогового окна. Возможно ли это?

public String getUserInput()
{
    //do something to show dialog
    String input = //get input from dialog
    return input;
}

Я на самом деле пытаюсь реализовать интерфейс, который имеет метод "public String getUserInput()", где возвращаемая строка должна быть восстановлена ​​через диалог. Это легко сделать в java, кажется невозможным в android?

РЕДАКТИРОВАТЬ: Проводка некоторого образца кода в соответствии с запросом в комментарии

getInput() должен быть вызван из фонового потока (я называю его из AsynchTask). getInput() отображает диалог и вызывает ожидание. Когда в диалоговом окне нажата кнопка ok, диалог устанавливает пользовательский ввод в переменной-члене и вызывает уведомление. Когда вызывается уведомление, 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;
}

Ответ 1

Спасибо за все отзывы, я смог решить это, используя фоновый поток вместе с wait() и notify(). Я признаю, что это не самая лучшая идея для данной парадигмы, но нужно было соответствовать библиотеке, с которой я работаю.

Ответ 2

Возможно ли это?

Нет. В Android нет блокировки модели пользовательского интерфейса. Все асинхронно.

UPDATE

В ответ на некоторые ваши комментарии по самому вопросу вы не можете отображать пользовательский интерфейс из фонового потока. Как я писал в этом ответе, в Android нет блокирующей модели пользовательского интерфейса. Просто поместите свой код в обработчик кнопки для своего диалога, который вы хотите выполнить, когда диалог будет принят, например, в этот примерный проект.

Ответ 3

Правильный способ сделать это - это программная модель, управляемая событиями, т.е. "не позвоните нам, мы вам позвоним".

В простом программировании в режиме консоли ваш код имеет тенденцию вызывать блокировку входных функций, которые не возвращаются, пока вы не получите значение.

Многие среды программирования gui работают по-разному - ваш код обычно не работает, но вместо этого он вызывается операционной системой/оконным менеджером, когда происходит что-то интересное. Вы делаете что-то в ответ на это и сразу возвращаетесь - если вы этого не сделаете, вы не можете быть уведомлены о чем-либо еще, так как у ОС нет возможности связаться с вами до вашего возвращения. (По сравнению с win32, как будто цикл сообщений реализован Android, и вы можете записать остальную часть кода, который цикл сообщений вызывает с событиями - если вы не вернетесь незамедлительно, зависает контур сообщения)

В результате вам нужно переосмыслить свою концепцию потока программ. Вместо того, чтобы записывать список дел в виде простой серии утверждений, подумайте об этом как о последовательности действий, которые зависят друг от друга и от ввода. Помните, какое действие вы сейчас используете в переменной состояния. Когда вы вызываетесь с событием, таким как ввод пользователя, посмотрите, означает ли это событие, что теперь можно перейти к следующему шагу, и если это так обновить переменную состояния перед оперативным возвратом в ОС, чтобы иметь возможность получить следующий мероприятие. Если событие было не тем, что вам было нужно, просто вернитесь без обновления состояния.

Если эта модель не будет работать для вас, то вы можете написать фоновый поток логики программы, который работает как приложение в консольном режиме, используя блокирующий вход. Но ваши функции ввода будут просто ждать флага или что-то, что будет уведомлено о том, что вход доступен. Затем в потоке пользовательского интерфейса, где Android отправляет события, вы обновляете флаг и сразу возвращаетесь. Фоновый поток видит, что флаг изменился, указав, что данные были предоставлены, и продолжает выполнение. (Что-то вроде эмулятора терминала android делает это до крайности, где фоновым компонентом на самом деле является другой процесс - консольный режим linux one, и он получает свои данные, используя потенциально блокирующий ввод-вывод из труб. Компонент java принимает события пользовательского интерфейса Android и заполняет символы в трубе stdin и вытаскивает их из канала stdout для отображения на экране.)

Ответ 4

Что-то подобное сделало бы

/**
 *
 */

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

Ответ 5

CASE: мои данные были готовы к процессам после события прослушивания изменения предпочтений, и мне нужно было добавить запрос String от пользователя. Невозможно открыть диалог оповещений, когда меню опций открыто... поэтому мне пришлось подождать. Я бросил половину полного объекта в следующую активность в рабочем процессе и установил onResume(), чтобы проверить, был ли его заполнитель! Null, и в этом случае я вытащил диалоговое окно и завершил объект * "в обработчике кнопок диалог" *.

Поскольку это мой первый пост, я не могу проголосовать за правильный ответ, указанный выше, но вы хотите, чтобы кто-то еще работал над этим временем и элегантностью менее правильных решений. Диалоговое окно - это место.

Ответ 6

Вы можете думать в терминах конечного автомата, где, если вы изначально требуете ввода пользователя в первый раз, вы можете установить флаг для отметки "пользовательский ввод" или что-то еще. Затем после обработки события вы проверяете этот флаг, и если он установлен, вы запускаете диалог как единственное действие для события и устанавливаете флаг. Затем из обработчика события диалога после обработки ввода пользователя вы можете вызвать код, обычно предназначенный для случая, когда диалог не требуется.