Come accedere vista di attività originaria di servizio in background generato
-
18-09-2019 - |
Domanda
Ho un'attività chiamato A, e sulla selezione della voce del menu 0, avvia servizio B, che avvia un C eseguibile in un nuovo filo. Ho un TextView nell'attività A, che voglio accedere in discussione C.
Ho provato a fare il TextView un campo statico pubblico, ma che genera il seguente errore:
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.checkThread(ViewRoot.java:2440)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChild(ViewRoot.java:522)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:540)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2332)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.view.View.invalidate(View.java:4437)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.updateAfterEdit(TextView.java:4593)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.handleTextChanged(TextView.java:5932)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6081)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.sendTextChange(SpannableStringBuilder.java:889)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:352)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:269)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:432)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:259)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:28)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2191)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at android.widget.TextView.append(TextView.java:2178)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at com.android.peekaboo.DoScan$scanBody.run(DoScan.java:36)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975): at java.lang.Thread.run(Thread.java:1058)
Ho anche considerato cercando di passare il Vista attraverso un intento, ma non so come dovrebbe funzionare. Di cosa ho bisogno per fare questo lavoro?
Soluzione
È necessario aggiornare i widget dal thread GUI, alias 'thread che ha creato la gerarchia vista'. Il metodo standard per farlo è tramite Handler
s ed un esempio di come utilizzare gestori possono essere trovati nella ProgressDialog Esempio ( ampliare 'Esempio ProgressDialog con un secondo filo').
Altri suggerimenti
ho avuto un problema simile in cui è stato richiesto un controllo ListView per essere aggiornato sulla risposta servizio web proveniente da un thread separato.
Dopo aver analizzato un simile domanda e esempio , ecco una soluzione che dovrebbe funzionare per voi:
public class A extends Activity implements Callback {
callserviceB () { } // where your service B being called;
@Override
public void returnServiceResponse() {
workOnResponse();
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
//update your view from here only.
}
}
}
public class B implements Runnable {
Callback callback;
public void run() {
//your business logic.
callback.returnServiceResponse();
}
}
public interface Callback {
public void returnServiceResponse();
}
È davvero non si vuole essere direttamente manipolare i widget da un servizio.
Ad esempio, supponiamo che l'utente fa scorrere la tastiera del suo G1. La vostra attività è distrutto e ricreato. Il vostro servizio, tuttavia, è tenuta su widget da un'attività ormai defunta. Nella migliore delle ipotesi, non si verificano gli aggiornamenti. Nel peggiore dei casi, gli aggiornamenti verranno causare un crash, o l'applicazione perderà la memoria perché la vecchia attività non può essere garbage collection, perché il servizio detiene ancora su di esso.
Avere servizi notificare attività va bene, fino a quando si dispone di isolamento decente tra di loro e l'attività si stacca dal servizio quando viene distrutta.
L'altro modo è quello di utilizzare os.android.AsyncTask per l'elaborazione.