2010-07-29 17 views
15

Me gustaría que las Actividades en la pila de actividades de mi aplicación solo tengan una instancia. Tengo varias pantallas que son ListActivities y me gustaría no pasar por el dolor y el sufrimiento de actualizar las listas en una instancia previa de ListActivity cuando otra instancia de esa ListActivity se cambia (se agrega, se edita, se elimina de, etc.) (¿o hay una manera fácil de hacer esto?).startActivityForResult no funciona correctamente con launchMode singleInstance

Nota: He leído que singleTop logrará esto (aunque destruye la actividad si presiona el botón Atrás), pero no funciona. Tengo un menú y si voy a la pantalla de la Bandeja de entrada, voy a la pantalla de Lista rápida y vuelvo a la pantalla de la Bandeja de entrada, y crea una nueva Actividad de Bandeja de entrada.

En este momento, en mi ListActivities, tengo launchMode configurado para singleInstance. El problema es: si lanzo otra actividad usando startActivityForResult, el controlador onActivityResult se dispara inmediatamente (antes de que se cree la nueva actividad). Cuando realizo la acción necesaria en la pantalla siguiente para devolver el resultado, el controlador onActivityResult no se activa.

¿Qué está pasando?

Aquí es cómo enciendo la nueva actividad:

Intent intentLaunchQuickList = new Intent(ActivityMyList.this, ActivityQuickList.class); 
startActivityForResult(intentLaunchQuickList, REQUEST_QUICKLIST); 

Aquí es cómo devolver el resultado:

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 
    super.onListItemClick(l, v, position, id); 
    QuickListItem qlItem = m_Adapter.getItem(position); 
    if (qlItem != null && qlItem.getQLId() != -1) { 
     Intent data = new Intent(); 
     data.putExtra("ql_id", qlItem.getQLId()); 
     if (getParent() == null) { 
      setResult(Activity.RESULT_OK, data); 
     } 
     else { 
      getParent().setResult(Activity.RESULT_OK, data); 
     } 
    } 
    finish(); 
} 

Aquí es mi manejador onActivityResult:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == REQUEST_QUICKLIST) { 
     if (resultCode == Activity.RESULT_OK) { 
      Bundle extras = data.getExtras(); 
      if (extras != null) { 
       int id = extras.getInt("ql_id"); 
       if (id > 0) { 
        launchQLItemsThread(id); 
       } 
      } 
     } 
    } 
} 

Respuesta

21

Desde el documentación de startActivityForResult: "Por ejemplo, si la actividad que está iniciando usa el singleTask modo de lanzamiento, no se ejecutará en su tarea y, por lo tanto, recibirá inmediatamente un resultado de cancelación ". singleInstance actividades son de la misma manera.

En otras palabras, si desea utilizar sAFR, tendrá que manejar varias instancias de actividad. Lo que aconsejaría es almacenar el estado de la lista para sus instancias ListActivity en en algún punto de la aplicación global (un singleton o lo que sea) y cargar desde allí en onResume. Entonces, incluso si se crean varias instancias de ListActivity, la superior siempre actualizará los datos antes de que se reanuden los anteriores, y las listas siempre serán actuales para el usuario.

Tenga en cuenta que debe hacer eso de todos modos si sus datos están destinados a ser persistentes, porque el sistema puede matar todo el proceso en cualquier momento después de una llamada , y si no ha guardado ningún cambio en el el tiempo que regresa, es probable que se pierdan en silencio bajo algunas circunstancias, a menudo raras e impredecibles. En este caso, desea utilizar archivos locales o bases de datos SQLite, que no persistan en la red. necesita regresar rápidamente porque el usuario no puede interactuar con el sistema mientras se está ejecutando, así que guárdelo en el almacenamiento local y luego sincronícelo con la red en algún otro momento, quizás a través de un servicio iniciado por .

+0

Gracias por su respuesta. Entiendo lo que quiere que haga, sin embargo, ¿no causará problemas? Obviamente tendré que hacer lo mismo en los controladores onSaveInstanceState y onRestoreInstanceState. Si en onResume y onPause leo y guardo información de la base de datos, mi aplicación leerá innecesariamente de la base de datos y leerá desde SavedInstanceState si alguna vez golpea el controlador onRestoreInstanceState, ¿sí? Además, ¿esto es realmente lo que es una práctica común para los desarrolladores de Android? ¿Guardar datos de ListActivity en un singleton para múltiples instancias de ListActivity? De nuevo, gracias por ayudar – Andrew

+0

Además, ¿podría explicar por qué singleTop no funciona para mí? ¿O no lo entiendo? – Andrew

+0

SavedInstanceState solo es útil para restaurar el estado de una instancia particular de una actividad; úselo para guardar la posición de desplazamiento, etc., no para mostrar el contenido. Lo que desea hacer es que todas las instancias de su actividad compartan algún estado, por lo que desea colocar ese estado en una base de datos si es persistente o en un miembro estático si solo se trata de un caché de datos de la red.Sugiero lo último en función de lo que ha dicho; solo use un DB para almacenar los datos que aún necesita enviar a través de la red en el futuro para que no los pierda. –

1

tengo varias pantallas que son ListActivities y me gustaría no ir a través del dolor y el sufrimiento de actualización de las listas en un instancia anterior del ListActivity cuando otro ejemplo de que es ListActivity cambiado (o hay una manera fácil de hacer esto?).

Utilice un modelo consistente. Por ejemplo, se espera que sus datos estén en una base de datos. Cada ListActivity tiene un Cursor en la parte de la base de datos que necesita. Tenga que Cursor sea un "Cursor administrado" (a través de startManagingCursor()), y su ListViews se actualizará automáticamente en onResume(). Luego realiza los cambios en su modelo a través de la base de datos.

que tienen un menú y si voy a la pantalla de mi bandeja de entrada , a continuación, voy a mi pantalla Lista rápida , y luego ir a la pantalla de mi bandeja de entrada de nuevo, se crea una nueva bandeja de entrada actividad.

Eso es lo que se supone que debe hacer. Citando las documentation:

Los modos de "estándar" y "singleTop" difieren entre sí en un solo respecto: Cada vez que hay nuevo intento para una actividad de "estándar", un nuevo instancia de la clase se crea al responder a esa intención. Cada instancia maneja un único intento. Del mismo modo, una nueva instancia de una actividad "singleTop" también se puede crear para manejar un nuevo intento . Sin embargo, si la tarea de destino ya tiene una instancia existente de la actividad en la parte superior de su pila, esa instancia recibirá el nuevo intento (en una llamada onNewIntent()); una nueva instancia no se crea. En otras circunstancias - por ejemplo, si una instancia existente de la actividad "singleTop" está en la tarea de destino , pero no en la parte superior de la pila, o si es en la parte superior de una pila, pero no en la tarea de destino: se crearía una nueva instancia de y presionó en la pila.

(negrita añadida para dar énfasis)

En este momento, en mis ListActivities, tengo launchMode establece en SingleInstance.

No haga esto.

+0

Gracias por su respuesta. ¿Podrían proporcionarme enlaces a información útil sobre cursores y bases de datos administrados? Todavía tengo que implementar una base de datos en una aplicación de Android. – Andrew

+0

Por el momento (comencé esta aplicación la semana pasada y es mi primera aplicación) simplemente estoy extrayendo datos de mis servicios web y completando la lista. Obviamente, la creación de una nueva instancia de la actividad necesitará extraer datos del servicio web nuevamente. Es por eso que comencé a usar singleInstance. Entiendo la lógica detrás de lo que estás diciendo. Aún tengo que implementar algo así; entonces algunos recursos serían útiles. Gracias de nuevo – Andrew

Cuestiones relacionadas