J'ai un problème avec l'erreur suivante dans Android:
CalledFromWrongThreadException ;: Only le thread d'origine qui a créé un hiérarchie de vue peut toucher ses vues
Il semble que cela se produise lorsque j'essaie de mettre à jour une vue de texte dans mon activité. L'appel à mettre à jour le TextView provient de mon activité, mais j'obtiens toujours l'erreur ci-dessus.
Je l'ai comme ça:
onCreate () - configure les boutons et la vue texte.
onStateChange () - un écouteur pour les notifications sur les changements d'état, lorsqu'il reçoit une notification si change le TextView pour dire un texte différent.
Lorsque je reçois une notification d'un nouveau texte, j'essaie de modifier le TextView de la manière suivante:
((TextView)findViewById(R.id.title)).setText("Some Text");
Mais je reçois l'erreur ci-dessus.
De googler, il semble que je devrais utiliser un gestionnaire pour modifier le TextView ou peut-être utiliser AsyncTask?
Quelqu'un pourrait-il expliquer lequel serait le mieux à utiliser et pourquoi?
EDIT: AJOUTS SNIPPETS CODE:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.my);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.my_title);
((TextView)findViewById(R.id.time)).setText("Hello Text");
findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"));
startActivity(dialIntent);
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
}
});
}
//CallBacks from running Service
private final ICallDialogActivity.Stub iCallDialogActivity = new ICallDialogActivity.Stub(){
@Override
public void onStateChanged(int callState)
throws RemoteException {
switch(callState){
case GlobalData.CALL_STATUS_IDLE:
break;
case GlobalData.CALL_STATUS_DISCONNECTING:
byeSetup();
break;
}
};
public void byeSetup(){
((TextView)findViewById(R.id.time)).setText("Bye Text");
findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//Void the Button
}});
}
On dirait que vous êtes sur le mauvais fil. Essayez d'utiliser un gestionnaire pour mettre à jour l'interface graphique sur le bon fil. Voir Gestion des opérations coûteuses dans le fil de l'interface utilisateur exemple sur Android.com. Fondamentalement, vous devriez insérer byeSetup
dans une Runnable
et l'invoquer avec une instance Handler
.
Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
public void run()
{
byeSetup();
}
});
Développer la réponse de willcodejavaforfood pour plus de clarté et de mise en œuvre ...
J'ai réussi à faire fonctionner cela et voici comment je l'ai fait. J'exécute plusieurs threads de traitement dans un service afin que les autres solutions exécutées dans Activity ne fonctionnent pas, comme runOnUiThread (new Runnable () {} ...
Placez ceci au sommet de votre classe de service afin qu'il soit accessible partout dans cette classe:
Handler handler;
Mettez ceci dans votre méthode onCreate de classe de service ou quelque chose qui se charge sur le fil principal du service
handler= new Handler(Looper.getMainLooper());
Mettez ceci dans votre fil supplémentaire dans le code "post back" pour s'exécuter dans l'interface utilisateur ou dans l'interface utilisateur du service (quel que soit le nom de l'appelant):
handler.post(new Runnable() {
public void run() {
playNext(); //or whatever method you want to call thats currently not working
}
});
Pour les autres, remplacez simplement byeSetup (); avec vos instructions de code ou méthodes. byeSetup () est un exemple de méthode. J'espère que cela vous fera gagner du temps.
Cette méthode est juste pour Activités et est préférable lorsque le changement implique le fil principal ( UiThread ). Utilisez-le à l'intérieur d'un autre thread pour modifier n'importe quelle vue.
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO your Code
et_Pass.setText("");
}
});
Une autre approche, utilisant cette fois Android.os.Message
Définissez Android.os.Handler
comme champ de votre activité:
private final Handler myTextHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message stringMessage) {
textView.append((String) stringMessage.obj);
return true;
}
});
Puis alimentez-le à partir de votre autre fil comme ceci:
Message stringMessage = Message.obtain(myTextHandler);
stringMessage.obj = "Hello!";
stringMessage.sendToTarget();
Vous pouvez utiliser la méthode post intégrée de view pour mettre à jour le contenu d'un autre fil, comme j'utilise le texte de modification dans kotlin.
address_box.post { address_box.text="my text"}