2010-12-07 13 views
34

Me gustaría implementar un método que muestre un cuadro de diálogo, espere hasta que se desestime el diálogo y luego devuelva un resultado según los contenidos del diálogo. es posible?Android: ¿espera la entrada del usuario desde el cuadro de diálogo?

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

De hecho, estoy tratando de implementar una interfaz que tiene el método "Cadena getUserInput pública()", donde la cadena devuelta debe ser recuperada a través de diálogo. Esto se hace fácilmente en Java, parece imposible en Android?

EDIT: Publicación de un código de ejemplo a lo solicitado en el comentario

getInput() debe ser llamado desde un subproceso de fondo (lo llamo desde una AsynchTask). getInput() muestra un diálogo y las llamadas esperan. Cuando se presiona el botón Aceptar en el diálogo, el diálogo establece la entrada del usuario en una variable miembro y las llamadas notifican. Cuando se invoca notify, getInput() continúa y devuelve la variable miembro.

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

No puede esperar al usuario en un método llamado en el subproceso de interfaz de usuario. Por lo tanto, debe cambiar a un modelo de flujo de programa impulsado por eventos o invocarlo desde un hilo de fondo que puede esperar hasta que un método onWhatever() invoque el hilo de UI en respuesta a la acción del usuario actualiza cualquier método de fondo que esté esperando. –

+0

Realmente no entiendo, ¿podría explicar cómo llamaría esto desde un hilo de fondo, y luego devolver mi cadena en lo que sea()? – ab11

+0

Porque si bloquearas el hilo de la IU por más de 3 (?), Creo que fueron tres segundos en los que recibirías una ventana emergente de diálogo ANR preguntándote si deseas cerrar la aplicación. Nunca ejecute material de bloqueo en el hilo de la interfaz de usuario en Android. –

Respuesta

11

Gracias por toda la retroalimentación, pude resolver esto usando una secuencia de fondo junto con una espera() y notificación () Reconozco que esta no es la mejor idea para el paradigma dado, pero era necesario ajustarse a una biblioteca con la que estoy trabajando.

+1

¿Puede publicar algún código? – Caner

+2

actualizó mi respuesta con un código – ab11

+0

muchas gracias! – Caner

1

Algo como esto haría

/** 
* 
*/ 

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


} 

El lanzamiento es:

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

obtener el resultado mediante el uso de

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

Podría estar equivocado, pero creo que esto no funcionará en absoluto para el problema que estaba describiendo ? He editado mi pregunta para aclarar el problema. – ab11

+0

Como describió, no es posible. Pero mis publicaciones proporcionan la forma en que puede hacerlo con una actividad que tiene un texto de entrada. – Pentium10

27

Es esto posible?

No. No hay un modelo de IU de bloqueo en Android. Todo es asincrónico.

ACTUALIZACIÓN

En respuesta a algunos de sus comentarios sobre la pregunta misma, no se puede mostrar una interfaz de usuario desde un subproceso en segundo plano. Como escribí en esta respuesta, no hay un modelo de UI de bloqueo en Android. Simplemente coloque el código en el controlador de botón para su cuadro de diálogo que desea ejecutar cuando se acepte el cuadro de diálogo, como en this sample project.

+0

¿Hay alguna razón especial para rechazar esta respuesta? –

+2

¿Quizás es la respuesta que alguien no quería escuchar? He tenido que suceder un par de veces. – blindstuff

+2

No puede mostrar directamente una IU desde una cadena de fondo, pero puede solicitar desde el hilo de fondo que la UI lo muestre por usted. –

10

La forma correcta de hacer esto es un modelo de programa impulsado por eventos, es decir, "no nos llame, lo llamaremos".

En la programación de modo de consola simple, su código tiende a llamar a las funciones de entrada de bloqueo, que no regresan hasta que haya obtenido un valor.

Muchos entornos de programación de interfaz gráfica de usuario funcionan de manera diferente: su código no se está ejecutando normalmente, sino que es invocado por el administrador del sistema operativo/ventana cuando ocurre algo de posible interés. Usted hace algo en respuesta a esto y regresa rápidamente; si no lo hace, no se le puede notificar nada más, ya que el sistema operativo no tiene forma de contactarlo hasta que regrese. (En comparación con win32, es como si el ciclo de mensajes fuera implementado por Android, y solo puede escribir el resto del código que el bucle de mensajes llama con eventos; si no regresa con prontitud, se cuelga el mensaje)

Como resultado, debe reconsiderar su concepto de flujo de programa. En lugar de escribir una lista de cosas por hacer como una simple serie de enunciados, piénselo como una secuencia de acciones que dependen unas de otras y de las entradas. Recuerde en qué acción se encuentra actualmente en una variable de estado.Cuando se le llama con un evento como la entrada del usuario, vea si ese evento significa que ahora es posible pasar al siguiente paso y, de ser así, actualice su variable de estado antes de volver al sistema operativo para poder recibir el siguiente evento. Si el evento no era lo que necesitabas, simplemente regresa sin actualizar tu estado.

Si este modelo no funciona para usted, lo que puede hacer es escribir un hilo de fondo de la lógica del programa que se ejecuta como una aplicación en modo consola usando la entrada de bloqueo. Pero sus funciones de entrada simplemente esperarán en una bandera o algo para ser notificado que la entrada está disponible. Luego, en su subproceso de interfaz de usuario donde Android entrega eventos, actualiza la bandera y regresa rápidamente. El hilo de fondo ve que el indicador ha cambiado para indicar que se han proporcionado datos, y continúa la ejecución. (Algo así como un emulador de terminal Android lleva esto a un extremo, donde el componente de fondo es en realidad otro proceso, un modo de consola de Linux, y obtiene su entrada utilizando bloqueos de E/S de las tuberías. El componente java acepta eventos de IU de Android y inserta caracteres en la tubería stdin y los saca de la tubería estándar para mostrar en la pantalla.)

0

CASO: Mis datos estaban listos para ser procesados ​​después de un evento de detector de cambios de preferencia y necesitaba agregar un String consultado por el usuario. No parece posible abrir un cuadro de diálogo de alerta mientras el menú de opciones está abierto ... así que tuve que esperar. Lancé el objeto medio completo a la siguiente actividad en el flujo de trabajo y configuré onResume() para comprobar si su marcador de posición era nulo, en cuyo caso extraje el cuadro de diálogo y finalicé el objeto * "en el controlador de botón del cuadro de diálogo "*.

Dado que esta es mi primera publicación, no puedo votar por la respuesta correcta dada anteriormente, pero quiero salvar a cualquiera que se encuentre con este el tiempo y la elegancia de las soluciones menos correctas. El diálogo es el lugar.

0

Puede pensar en términos de una máquina de estado donde si inicialmente necesita la entrada por primera vez del usuario, puede tener un indicador configurado para marcar "la entrada del usuario necesaria" o lo que sea. Luego, al procesar un evento, verifica ese indicador y, si lo configura, inicia un diálogo como la única acción para el evento y desarma la bandera. Luego, desde el controlador de eventos de diálogo después de manejar la entrada del usuario, puede llamar al código normalmente destinado para el caso cuando no se necesita un diálogo.

0

Tuve un momento difícil para entender todas las soluciones ofrecidas hasta ahora, así que encontré la mía.

envuelvo los códigos de eso va a ser ejecutada después de la entrada del usuario se OK'ed en un ejecutable, así:

Runnable rOpenFile = new Runnable() { 
     @Override 
     public void run() { 
      .... code to perform 
     } 
    } 

Luego a la derecha por debajo de ese paso el nombre de la función ejecutable para el usuario método de diálogo.

userInput("Open File", rOpenFile); 

El método userInput se basa en el constructor alertDialog como se describió anteriormente. Cuando la entrada del usuario está Ok'ed, inicia el ejecutable deseado.

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