2010-12-14 8 views
5

Tengo un widget que necesita realizar una operación potencialmente de larga ejecución en onUpdate(). solo realizar la operación resultó directamente en ANR. para resolver esto, mi primer intento fue crear un hilo en el mismo. Noté que el widget no se actualizaría en algunos casos. mi suposición aquí es que una vez que onUpdate() se cierra, android puede matar el proceso junto con el hilo inacabado.android operación de larga duración para actualizar un appwidget

mi próximo intento fue crear un servicio intencionado. el widget onUpdate() solo inicia el servicio de intención, que hace el trabajo directamente y actualiza el widget cuando termina. esto funciona, pero para mi sorpresa, parece que onHandleIntent() tiene un solo subproceso. si tengo dos widgets, y luego ambos actualizo e inicio el servicio de intento, se actualizan secuencialmente ...

el caso de los dos widgets no es realmente importante, pero me pregunto sobre una mejor práctica para este tipo de patrón .

para resolver el caso de dos widgets terminé actualizando todas las instancias de widgets con los mismos datos cada vez que se hace clic en alguno de ellos. Por ejemplo, realizo el proceso de larga ejecución una vez y aplico los resultados a todas las instancias de widgets. en mi caso esto no importa, pero para muchos widgets podría ser importante no hacer eso.

thoughts?

Respuesta

3

pero para mi sorpresa parece que onHandleIntent() es el único subproceso

Sí.

si tengo dos widgets, y luego ambos actualización e iniciar el servicio intención, se actualizará de forma secuencial ...

Sí.

pero me pregunto acerca de una mejor práctica para este tipo de patrón.

Su IntentService fue una excelente solución, en mi humilde opinión. Recuerde que Android se ejecuta en CPU lentas, con dispositivos con poca memoria RAM. Correr muchos hilos en paralelo generalmente no es una buena idea.

luego estoy empezando a iniciar un hilo enHandleIntent(), que requiere un bloqueo de activación, y parece que se está volviendo demasiado complicado.

Pruebe mi WakefulIntentService.

+0

está bien si lo entiendo correctamente. 1) widget inicia el servicio intencionado para obtener datos y actualizar el widget cuando está hecho 2) el servicio intenta obtener un bloqueo de activación, y comienza un hilo para hacer el trabajo real, y luego actualiza el widget cuando está hecho 3) cuando termina el hilo, lo libera La cerradura. chico que suena complicado. ¿Por qué no puedo simplemente bloquear un bloqueo en la aplicación de texto HANDLEIntent()? –

+0

@ farble1670: Porque el dispositivo podría quedarse dormido antes de llegar allí. – CommonsWare

+0

lo siento, quise decir agarrar un candado enHandleUpdate(), en el appwidget impl. ¿Qué me permite enviar la solicitud a un servicio intencionado? –

0

make onUpdate llame a su propia función para recorrer los widgets y actualizarlos. Haga su tarea de sincronización antes del ciclo. Querrá dos acciones separadas, una que solicite que se inicie la actualización y otra que su IntentService transmitirá para que los widgets sepan que terminaron. Espero que esto ayude.

@Override 
public void onUpdate(Context context, AppWidgetManager appWidgetManager, 
     int[] appWidgetIds) { 
    updateWidget(context, appWidgetManager, appWidgetIds); 
} 

private void updateWidget(Context context){ 
    ComponentName widget = new ComponentName(context, MyWidget.class); 
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); 
    int[] appWidgetIds = appWidgetManager.getAppWidgetIds(widget); 
    updateWidget(context, appWidgetManager, appWidgetIds); 
} 

private void updateWidget(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 

    final boolean isEnabled = true; //took out code didn't want you to see 
    // start intent service here 
    for(int i = 0; i< appWidgetIds.length; i++){ 
     int appWidgetId = appWidgetIds[i]; 
     Intent intent = new Intent(isEnabled ? ACTION_TOGGLE_OFF : ACTION_TOGGLE_ON); 
     PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0); 

     RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); 
     views.setOnClickPendingIntent(R.id.widget , pi); 
     views.setImageViewResource(R.id.widget_image, isEnabled? R.drawable.widget_on : R.drawable.widget_off); 

     appWidgetManager.updateAppWidget(appWidgetId, views); 
    } 
} 
+0

hmmm, no estoy seguro de cómo se aplica esto. empezar desde el principio. en onUpdate(), realice un proceso de ejecución larga, luego actualice todos los ID. el proceso de larga ejecución no puede simplemente ejecutarse en el subproceso onUpdate(), que causará un ANR. entonces, usa un servicio intencionado pero esto tiene un único subproceso, por lo que si varias llamadas onUpdate() provienen de múltiples widgets, lo que resulta en múltiples llamadas al servicio de intención, el segundo widget se bloquea esperando que el primero termine en el servicio intencionado. –

+0

esta es la razón por la que debería llamarlo antes de completar el ciclo y actualizar sus widgets, básicamente se hará cargo de la convención que tenía Google en el lugar que actualiza todos los widgets para usted. La función de actualización solo debería manejar los cambios de UI, entonces tendría una instrucción if/else o switch para determinar cuál es la acción actual (iniciar el hilo, progreso del hilo, hilo terminado) – schwiz

+0

bien ... mi primera pregunta que supongo se perdió se trata de comenzar el hilo. si está bien iniciar un hilo en onUpdate() y regresar? ¿No necesito agarrar un candado? ¿matará android el proceso después de que sale onUpdate()? hacer que inicie un servicio intencionado en lugar de un hilo parece evitar el ANR, pero no funciona cuando hay múltiples widgets actualizados, ya que se colgarán esperando que onHandleIntent() salga. entonces estoy empezando a iniciar un hilo enHandleIntent(), que requiere un bloqueo de activación, y parece que se está volviendo demasiado complicado. –

Cuestiones relacionadas