Android startService () tarda mucho tiempo en volver al subproceso de interfaz de usuario

mi usecase es (aproximadamente) lo siguiente en la primera puesta en marcha:

  1. la actividad inicia un servicio
  2. servicio obtiene y guarda datos en una base de datos
  3. servicio notifica la actividad con una intención
  4. la actividad muestra datos

Ahora quiero mostrar una barra de progreso mientras el servicio está ocupado. El problema es:

startService(new Intent(getApplicationContext(), UpdateDataService.class));

toma mucho tiempo para "volver" al hilo de la interfaz de usuario. Parece ser una función sincronizada (o no ?). Si se vacía la clase de servicio, el comando startService se procesa casi instantáneamente. Parece que el hilo de la interfaz de usuario espera a que el Serice maneje su trabajo, que no tiene sentido en absoluto. Intenté iniciar (por estúpido que parezca) para iniciar el servicio una tarea asíncrona mientras se muestra una barra de progreso en mi subproceso de interfaz de usuario. Curiosamente esto funciona a veces. Otras veces sólo recibo una pantalla en blanco mientras mi servicio está funcionando y después por un millisecond ma progressbar y luego mi interfaz de usuario.

Ahora mi pregunta: ¿Cómo puedo iniciar el servicio sin bloquear mi interfaz de usuario?

 public class MyClass extends TabActivity { private ProgressDialog pd; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent intent = null; //building some tabs here, setting some text views.... // starting service if does not exist yet boolean serviceRunning = false; final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) { serviceRunning = true; Log.i(MY_APP_TAG, "Service found."); } } if (!serviceRunning) { pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false); new StartServiceAsync().execute(""); } } private final Handler handler = new Handler() { @Override public void handleMessage(final Message msg) { pd.dismiss(); } }; public class StartServiceAsync extends AsyncTask<String, Void, String> { @Override protected String doInBackground(final String... params) { // starting service startService(new Intent(getApplicationContext(), UpdateDataService.class)); return null; } @Override protected void onPostExecute(final String result) { handler.sendEmptyMessage(0); super.onPostExecute(result); } } 

Creo que debería mover la lógica del servicio al método doInBackground en la tarea asíncrona. Eso es lo que la tarea asíncrona son para ejecutar el trabajo duro que le da una manera sencilla de interactuar con la interfaz de usuario. Es extraño llamar a un servicio en la tarea asíncrona, ¿hay alguna razón por la que lo hiciste?

Del tema de la guía Servicios :

Precaución: Un servicio se ejecuta en el mismo proceso que la aplicación en la que se declara y en el subproceso principal de esa aplicación, de forma predeterminada. Por lo tanto, si su servicio realiza operaciones intensivas o de bloqueo mientras el usuario interactúa con una actividad de la misma aplicación, el servicio ralentizará el rendimiento de la actividad. Para evitar impactar el rendimiento de la aplicación, debe iniciar un nuevo subproceso dentro del servicio.

Esto no cambia sólo porque llama a startService desde un AsyncTask.

Haga su trabajo en AsyncTask sí mismo, utilice un IntentService vez de un Service viejo llano o comience un hilo de su Service para hacer su trabajo. Un Service en Android no utiliza inherentemente un hilo diferente ( IntentService hace para hacer su trabajo).

A pesar de comenzar su Service de un AsyncTask , ahora parece que el trabajo real se está realizando en su hilo de interfaz de usuario.

por favor use este código de la manera fácil de hacer lo que pidió en cuestión.

 @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent intent = null; registerReceiver(dataUpdated, new IntentFilter("<FLAG>")); //building some tabs here, setting some text views.... // starting service if does not exist yet boolean serviceRunning = false; final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) { serviceRunning = true; Log.i(MY_APP_TAG, "Service found."); } } if (!serviceRunning) { pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false); startService(new Intent(getApplicationContext(), UpdateDataService.class)); } } private BroadcastReceiver dataUpdated= new BroadcastReceiver() { @SuppressLint("ShowToast") @Override public void onReceive(Context context, Intent intent) { //<Your Process which you want when Service finishes a task > pd.dismiss(); } }; @Override protected void onDestroy() { unregisterReceiver(dataUpdated); } 

En servicio cuando la tarea se complete llame a este método

 sendBroadcast(new Intent("<FLAG>")); 
  • Cómo dar formato al tiempo no fecha en Android o Java?
  • ¿Cómo cambiar el nombre de la aplicación de Android y el icono en tiempo de ejecución?
  • Formato de fecha y hora
  • Cómo obtener el tiempo de computación en NDK
  • android: mostrar la notificación en un momento específico?
  • ¿Cómo obtener la hora actual de Google para Android?
  • SoundPool de Android tartamudea, retrasa, a veces no juega en absoluto
  • Android - Obtener el widget del cronómetro
  • Static static String definida en una interfaz no evaluada en tiempo de compilación - Android
  • ¿Cómo se puede comprobar el permiso en tiempo de ejecución sin lanzar SecurityException?
  • Android: ¿Activar / desactivar un botón en Runtime?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.