2010-05-21 9 views
6

Llamo a una subactividad de la actividad principal. Esta subactividad debe tomar pocos números del usuario (estoy usando el control de edición de texto para lograr esto), guardarlos en una variable estática en otra clase y terminar. Quiero que la actividad principal espere a la subactividad, pero ambas solo se ejecutan simultáneamente. Incluso hacer algo así no ayuda:¿Cómo forzar a la actividad principal a esperar la subactividad en Android?

 Thread t = new Thread(new Runnable(){ 
    public void run(){ 
    Log.v("==================", "run "+new Date()); 
    startActivityForResult(new Intent(ctx,myCustomSubactivity.class),1); 
    } }); 
    Log.v("==================", "calling run "+new Date()); 
    t.start();  
    try { 
     t.join(); 
    } catch (InterruptedException e) {Log.v("==================", "can't join");} 
    Log.v("==================", "back from activity "+new Date()); 

¿sabes cómo obligar a la actividad principal a esperar? El método Thread.wait() no es compatible con Android (el programa arroja un error).

Respuesta

3

Estoy de acuerdo con Nikolay, esta es definitivamente la forma de Android para hacer esto.

Comience la subactividad con startActivityForResult en la subactividad use setResult para agregar un código de resultado y una intención con todos los números que necesita en el paquete de datos.

En su primera actividad, sobrescriba onActivityResult y recupere los números del Intento.

Si usa la variable estática, esto parece más fácil en el primer momento pero es muy inseguro y en algunos casos esto puede no funcionar. Si su programa se envía a segundo plano, sus actividades se guardarán, pero si el teléfono tiene poca memoria, el sistema cerrará su programa y, una vez que el usuario lo reanude, todo se ve como el momento en que el usuario lo dejó, pero las variables estáticas se volverán a crear. su valor de inicialización.

Trate de acostumbrarse a la forma en que funciona el android activity lifecycle. El uso de este enfoque dará como resultado menos memoria usada y una experiencia de usuario mucho mejor.

2

Bueno ... puede hacerlo de esta manera (por cierto, no hay manera directa):

tener una clase Singleton, llamémoslo monitor:

public class Singleton 
{ 
    private Singleton() { } 
    private static Singleton instance = new Singleton(); 

    public static Singleton getInstance() { 
     return instance; 
    } 
} 

public class ParentActivity extends Activity 
{ 
    private void startAndWait() 
    { 
     Intent i = new Intent(); 
     // initialize i 
     startActivityForResult(i); 
     Singleton si = Singleton.getInstance(); 
     synchronized(si) 
     { 
      si.wait(); 
     } 
     //do remaining work 
    } 
} 

public class ChildActivity extends Activity 
{ 
     protected void onCreate(Bundle savedInstance) 
     { 
      //do all the work 
      Singleton si = Singleton.getInstance(); 
      synchronized(si) 
      { 
      si.notify(); 
      } 
     } 
} 
+0

este código se compila pero subactividad no se dispara. Tengo un mensaje allí en OnCreate para iniciar sesión si se está ejecutando ChildActivity pero no hay tal entrada en el registro. No sé qué salió mal;> – questioner

+0

intente poner ..................................... ........................ Singleton si = Singleton.getInstance(); sincronizado (si) { si.wait(); } en postDelayed (...); –

+0

No estoy familiarizado con postDelay (r, t); pero lo leí y lo intenté, pero sin éxito, "la aplicación no responde, fuerza cerca" Creo que esperar y notificar en Android no funcionan correctamente – questioner

7

Puede ser que soy falta algo, pero ¿por qué no usar el mecanismo startActivityForResult y onActivityResult? Podría obtener el resultado de su subactividad por la intención con la que se produjo.
Edición: Por cierto, por lo que entiendo, si ejecuta Object.wait() desde el código Activity si va a contener la banda de rodamiento de la IU que puede dar como resultado el error Application not responding.

3

Echa un vistazo a Notepad example, cubre exactamente esta situación. Y como otros han dicho, la forma de Android es hacer que su primera actividad inicie su segunda actividad (¡no subactividad!) Y escuche de forma asíncrona una respuesta (no pause o wait, no need to join, etc.).

2

No estoy aquí para juzgar si es un buen patrón o no, pero si realmente se necesita una actividad que esperar para un sub-actividad, se puede intentar este enfoque:

  • definir un objeto (bloqueo) sobre el cual las dos actividades se sincronizan; esto también puede (debería) funcionar como el objeto para intercambiar datos entre esas dos actividades y debe definirse como estático
  • en actividad principal, iniciar una tarea asíncrona (como el hilo principal de la interfaz de usuario no puede estar en estado de espera)
  • en la tarea asíncrona, inicie su subactividad
  • la tarea asíncrona espera en la cerradura hasta que se notificó
  • la subactividad hace lo que necesita y lo notifica al hilo de espera cuando termina

I hice algo similar en mi aplicación y en mi humilde opinión tenía una buena razón para esto (no molestarnos Con la pantalla de inicio de sesión al iniciar o reanudar la aplicación, la aplicación intenta volver a usar las credenciales almacenadas en un lugar seguro y solo en caso de que falle, muestra esta pantalla de inicio de sesión. Así que sí, básicamente cualquier actividad en mi aplicación puede "pausarse" y esperar hasta que el usuario proporcione las credenciales correctas en la actividad de inicio de sesión cuando finaliza la pantalla de inicio de sesión y la aplicación continúa exactamente donde se detuvo (en la actividad principal).

En el código sería algo como esto:

ParentActivity:

public class ParentActivity extends Activity { 
    private static final String TAG = ParentActivity.class.getSimpleName(); 

    public static class Lock { 
     private boolean condition; 

     public boolean conditionMet() { 
      return condition; 
     } 

     public void setCondition(boolean condition) { 
      this.condition = condition; 
     } 
    } 

    public static final Lock LOCK = new Lock(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.parent_layout); 

     // do whatever logic you need and anytime you need to stat sub-activity 
     new ParentAsyncTask().execute(false); 
    } 

    private class ParentAsyncTask extends AsyncTask<Boolean, Void, Boolean> { 

     @Override 
     protected Boolean doInBackground(Boolean... params) { 
      // do what you need and if you decide to stop this activity and wait for the sub-activity, do this 
      Intent i = new Intent(ParentActivity.this, ChildActivity.class); 
      startActivity(i); 
      synchronized (LOCK) { 
       while (!LOCK.conditionMet()) { 
        try { 
         LOCK.wait(); 
        } catch (InterruptedException e) { 
         Log.e(TAG, "Exception when waiting for condition", e); 
         return false; 
        } 
       } 
      } 
      return true; 
     } 
    } 
} 

ChildActivity:

public class ChildActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.child_layout); 

     // do whatever you need in child activity, but once you want to finish, do this and continue in parent activity 
     synchronized (ParentActivity.LOCK) { 
      ParentActivity.LOCK.setCondition(true); 
      ParentActivity.LOCK.notifyAll(); 
     } 
     finish(); 

     // if you need the stuff to run in background, use AsyncTask again, just please note that you need to 
     // start the async task using executeOnExecutor method as you need more executors (one is already occupied), like this: 
     // new ChildAsyncTask().executeOnExecutor(ChildAsyncTask.THREAD_POOL_EXECUTOR, false); 
    } 

} 
Cuestiones relacionadas