2012-03-16 23 views
5

Ancora una domanda su LocalServices. Come faccio a (re) legare a un servizio esistente, dopo onDestroy()?associazione al servizio in esecuzione (dopo il completamento())/callback Handler

Il problema: Sono impegnativo per un servizio e avvio del servizio da un'attività. Sto postando oggetti eseguibili sul Raccoglitore, per una richiamata (aggiornando una barra di avanzamento) sull'interfaccia utente. Quando chiudo questa attività, il sistema operativo potrebbe terminare il ciclo di vita e distruggere l'attività, chiamando onDestroy(), giusto? Lo simulo, chiamando finish() nel metodo onPause(). Quindi, una volta riavviata l'attività, come associare nuovamente il servizio SAME? Pensavo che i Servizi fossero Singelton, ma quando cerco di ri-legare, ottengo un'altra referenza. Quindi binder.callbackHandler.post(binder.progressHandler); ha ancora il riferimento al vecchio raccoglitore/callback/progressHandler, non al mio nuovo. Anche il costruttore del servizio viene richiamato!

C'è una soluzione per avere una barra di avanzamento, che viene aggiornata dagli oggetti di richiamata dal servizio (funzionante). Chiudere/onDestroy() l'attività. Torna indietro e continua la barra di avanzamento?

Il mio codice è abbastanza grande, ma ha ricreato lo Szenario:

public class MyService extends Service { 
     private final LocalBinder binder = new LocalBinder(); 

     public class LocalBinder extends Binder implements TestRunServiceBinder { 
      private Handler callbackHandler; 
      private ServiceStartActivity.RunOnServiceProgress onProgress; 

      @Override 
      public void setActivityCallbackHandler(Handler messageHandler) { 
       callbackHandler = messageHandler; 
      } 

      @Override 
      public void setServiceProgressHandler(RunOnServiceProgress runnable) { 
       onProgress = runnable; 
      } 

       public void doSomething(){ 
        _doSomething(); 

     }; 

     private void _doSomething(){ 
     while(...){ 
      //do this a couple of times (could take up to 10min) 
      binder.callbackHandler.post(binder.progressHandler); 
      wait() 
     } 
     } 

    } 

_

public class ServiceStartActivity{ 
private final Handler messageHandler = new Handler(); 
    private ServiceConnection mTestServiceConnection = new ServiceConnection() { 


     @Override 
     public void onServiceDisconnected(ComponentName name) { 
      testRunBinder = null; 
     } 

     @Override 
     public void onServiceConnected(ComponentName name, IBinder service) { 
      testRunBinder = (TestRunServiceBinder) service; 
      testRunBinder.setActivityCallbackHandler(messageHandler); 
      testRunBinder.setServiceProgressHandler(new RunOnServiceProgress()); 
     } 
     }; 

    @Override 
    protected void onStart() { 
    super.onStart(); 

    // bind to the Service 
    final Intent serviceIntent = new Intent(ServiceStartActivity.this, 
      MyService.class); 
    getApplicationContext().bindService(serviceIntent, 
      mTestServiceConnection, Context.BIND_AUTO_CREATE); 

    } 
    @Override 
    protected void onStop() { 
    super.onStop(); 
    getApplicationContext().unbindService(mTestServiceConnection); 
    } 
     public class RunOnServiceProgress implements Runnable { 
      @Override 
      public void run() { 
       //do something on the UI! 
        } 
     } 
} 

risposta

8

ho ottenuto ora. La soluzione è quella esplicita chiamata startService(serviceIntent); prima si associa al Servizio utilizzando getApplicationContext().bindService(serviceIntent,mTestServiceConnection, Context.BIND_AUTO_CREATE);

Motivo: Quando si avvia un servizio con bindService(), diventa un servizio Bound un

corse solo fino a quando un'altra applicazione componente è associato ad esso.

Se si avvia un servizio con startService() può

può essere eseguito in background a tempo indeterminato,

Quindi, se avete ad esempio una barra di avanzamento sull'interfaccia utente e si desidera che continui ad aggiornarla, è necessario avviare il servizio e associarlo e annullarlo in onResume()/onPause(). Ma fai attenzione: dal momento che hai avviato il servizio manualmente, , dovresti anche arrestarlo manualmente. Il modo più semplice per farlo è chiamare il stopSelf() una volta che il servizio ha funzionato.

Questa anima copre un legame corretto da un'attività con ad es. una barra di progresso per lo stesso servizio anche dopo che l'attività è stata distrutta o dopo un cambio di orientamento.

+0

ha funzionato per me. Ricorda che se si utilizza getApplicationContext() quando si esegue il bind, utilizzarlo di nuovo quando si disattiva. – fersarr

Problemi correlati