2012-04-27 11 views
6

Tengo una operación de base de datos de actualización, que tiene una actividad, que sigue actualizando el porcentaje y se ejecuta dentro de una tarea AsyncTask.Actualizar la IU mientras se trabaja en el fondo

DoInBackground interior() Llamo al controlador que actualiza la base de datos y sigo actualizando el porcentaje de la actividad; sin embargo, si presiono el botón de inicio o el botón de retroceso, la operación se cancela. ¿Qué me sugieres que haga?

Estaba intentando iniciar un servicio dentro de doInBackground() para que se ejecute en segundo plano, pero parece que no está funcionando.

Mi código es el siguiente:

public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer> 
{ 
    @Override 
    public void onPreExecute() 
    { 
     mCustomProgressBar.startAnimation(); 
    } 

    @Override 
    public Integer doInBackground(Void... params) 
    { 
     return mController.updateDatabase(); 
    } 

    @Override 
    public void onPostExecute(Integer result) 
    { 
     mCustomProgressBar.stopAnimation(); 
     // finish the activity 
    } 

    @Override 
    public void onProgressUpdate(Integer... value) 
    { 
     updatePercentageValue(value[0]); 
    } 

    public void callPublishProgress(Integer value) 
    { 
     publishProgress(value); 
    } 
} 

Y dentro del controlador que llamar al método callPublishProgress(value) pasando el valor actual porcentaje, por lo que publishProgress(value) en la interfaz de usuario.

Estaba depurando, y presioné el botón de inicio/atrás, y simplemente dejó de ejecutar el hilo de trabajo.


Otra solución intenté, fue iniciar un servicio a ejecutar en segundo plano sin importar el botón de prensa usuario doméstico/vuelta o no, así que pensé, y el Servicio haría una llamada al método controlador que hace el trabajo, y llamaría al callPublishProgress(value) para actualizar el valor del porcentaje en la interfaz de usuario de todos modos.

Sin embargo, lo que estaba ocurriendo es, el código alcanzar doInBackground() e iniciar el servicio, sino que va a onPostExecute() de inmediato, simplemente no se hizo esperar el servicio para terminar (por supuesto!). Entonces da un NullPointerException. Pensé en hacer un ciclo dentro de doInBackground() con un marcador establecido en el Servicio, por lo que dejaría este bucle mientras el servicio no se había terminado (estaba usando un Servicio de Intención), pero no funcionó de todos modos.

Pensé en usar un temporizador también. Pero no sé

Estaba leyendo los artículos en la documentación sobre Hilos, etc. Y sugiere usar AsyncTask, justo como estaba tratando de hacer. También habla de runOnUiThread(Runnable).

De todos modos, lo que necesito es hacer una operación en segundo plano (probablemente usando un servicio de intención), así que no importa si el usuario presiona el botón de inicio, seguirá funcionando, pero debe actualizar el porcentaje en la interfaz de usuario y cuando el usuario abandona la pantalla y vuelve a ella, muestra el valor de porcentaje actual actualizado en la pantalla.

¿Cuál es la mejor solución para mi caso?

Gracias.

+0

Ver las demostraciones del API en las muestras de SDK, hay un ejemplo de un servicio que cuenta y notifica una actividad de primer plano que puede mostrar el recuento. –

+0

¿Cuál es el nombre de esta muestra? – rogcg

+0

No recuerdo exactamente, todo está en la aplicación demos de la API en el directorio samples/de la sdk: compila todo, ejecútalo y examina los menús, y examina el código. También hay muchas otras cosas útiles que vale la pena conocer. –

Respuesta

3
public class MyServce extends Service{ 
public static final String BROADCAST_ACTION = "com.myapp"; 
Intent intent; 
private final Handler handler = new Handler(); 

@Override 
public void onCreate() 
{ 
    super.onCreate(); 
    intent = new Intent(BROADCAST_ACTION); 
} 

@Override 
    public void onStart(Intent intent, int startId) { 
     handler.removeCallbacks(sendUpdatesToUI); 
     handler.postDelayed(sendUpdatesToUI, 1000); // 1 second 

    } 
    private Runnable sendUpdatesToUI = new Runnable() { 
     public void run() { 
      DoYourWorking();   
      handler.postDelayed(this, 1000); // 1 seconds 
     } 

     private void DoYourWorking() { 
     ........ 
        ........ 
        intent.putExtra("key", progress); 
      sendBroadcast(intent); 

     } 
    }; 

@Override 
public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 
    return null; 
} 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    handler.removeCallbacks(sendUpdatesToUI);  

} 

En su actividad de difusión registro para el servicio

private BroadcastReceiver brodcast = new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
       //intent.getWhatever 
     // update your progress 
     //progressbar.setProgress 
    } 

emisión registro

registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION)); 
+0

Funciona como un amuleto, pero no necesitaba usar un controlador. Acabo de iniciar IntentService, y de IntentService llamé sendBroadcast (Intención). ¡Muchas gracias! – rogcg

1

Esto funcionó para mí. Inicié un servicio en segundo plano en un hilo que simplemente recupera los valores y actualiza un objeto en un singleton.

En el controlador de vista, inicio un temporizador que sigue actualizando la vista obteniendo datos del objeto en singleton.

Tuve un pequeño problema para entender todo el texto de tu pregunta, por lo que no estoy seguro de si lo has intentado. Pero esto es lo que funcionó.Además, el servicio se inició con START_STICKY

1

Utilice un IntentService (que es un servicio en un hilo propio) y Handler para pasar los datos a la Actividad.

Cuestiones relacionadas