2010-11-29 40 views
2

Bon après-midi.Android - Fin de l'activité depuis le fil de rendu

Je ne suis pas familier avec le cycle de vie de l'activité dans android et ai lu le mieux possible, mais je ne peux pas comprendre comment résoudre ce qui suit d'une manière agréable.

J'ai une activité avec un GLSurfaceView pour dessiner diverses choses à l'écran. Dans le thread de rendu pour cette GLSurfaceView, j'effectue tout le rendu ainsi que la logique de mise à jour actuelle (je vais séparer cela éventuellement). Le problème que je rencontre provient d'un des "écrans" dessinés dans le moteur de rendu. Je souhaite terminer l'activité et appeler les différentes méthodes du cycle de vie.

Normalement, je peux le faire avec System.exit (0); Cependant, terminer l'activité de cette manière ne semble pas appeler OnStop(); OnDestroy(); méthodes

Cela pourrait juste être moi être bête et ne pas voir une manière facile de le faire mais est-il un moyen d'accéder à l'activité et appeler activity.finish(); sans avoir à passer la référence tout en bas?

Ceci est probablement moins d'une question android et plus un problème java général? Désolé je suis un peu rouillé à la fois. Peut-être que quelqu'un pourrait expliquer à peu près comment ils gèrent un problème comme celui-ci dans leur application.

Répondre

5

Vous devez respecter les règles de sécurité des threads et ne pas appeler activity.finish() directement à partir de votre thread de rendu. La meilleure façon de gérer cela est de renvoyer un exécutable dans la file d'attente des événements pour le thread UI. Et laissez ce Runnable appeler activity.finish().

Vous n'avez pas besoin de transmettre l'activité à la zone où vous prévoyez d'arrêter l'activité. Voici ce que je ferais. Passez l'activité à la classe que vous instanciez dans onCreate(). Quelque chose comme:

public void onCreate(...) { 
    MyRenderer renderer = new MyRenderer(glSurface, this); 
} 

alors à l'intérieur MyRenderer je ferais quelque chose comme:

public void someMethodInRenderer() { 
    if(stop) { 
     stop(); 
    } 
} 

public void stop() { 
    Handler handler = new Handler(); 
    handler.post(new Runnable() { 
     public void run() { 
     activity.finish(); 
     } 
    }); 
} 

Notez que le gestionnaire est utilisé pour écrire au thread d'interface utilisateur. Cela rend sûr d'appeler activity.finish(). Je n'ai pas trouvé d'informations spécifiques dans les documents indiquant qu'il est sûr ou pas sûr d'appeler finish() à partir d'un autre thread pour être du bon côté.

Choses à garder à l'esprit. Si someMethodInRenderer() est profond dans les entrailles de votre programme, vous n'avez pas besoin d'avoir accès directement à l'instance d'activité. Vous avez juste besoin d'une référence pour que quelque chose finisse par appeler l'activité. Donc peut-être il y a une référence à une autre partie du système que vous transmettez à cette méthode où vous pouvez ajouter le stop(). Ainsi, stop() et someMethodInRenderer() pourraient être dans la même classe, ou dans des classes différentes. C'est un choix que vous devrez faire. Finalement, c'est un problème d'architecture que vous devez décider.

+0

Merci, je revenais juste pour éditer ma question et mettre "ceci est probablement plus d'une question d'architecture/meilleure pratique". Étant autodidacte, j'ai tendance à savoir comment faire quelque chose, mais je doute toujours que ce soit la meilleure pratique pour le faire ou même en toute sécurité! – iexus

+0

Après avoir réfléchi un peu plus, j'ai réalisé que vous auriez besoin de créer le gestionnaire dans le thread UI, donc dans le OnCreate() ou bien il est fait dans le thread de rendu et ne peut pas poster? Est-ce correct? – iexus

+0

Oui Je crois que vous devrez peut-être créer le gestionnaire sur le thread d'interface utilisateur, puis passer à votre moteur de rendu. Encore une fois, vous pouvez utiliser des astuces d'architecture en acheminant les appels à travers des parties de votre architecture de sorte que vous ne deviez pas passer des références jusqu'au point où stop() est appelé. – chubbsondubs

1

Si le thread de rendu se trouve dans l'activité, vous pouvez utiliser ActivityClassName.this.finish();

1

Pour répondre à une question que je suis tombé sur:

Si vous avez terminé votre activité (y compris un autre thread) par l'intermédiaire activity.finish() il est important que la méthode de fil render onDraw() n'est pas bloqué (qui est arrivé à moi en raison de mon implémentation du rendu du double tampon).

Dans ce cas, seule la méthode onPause() de la classe d'activité a été appelée. Les méthodes onStop() et onDestroy() n'ont pas été appelées même si l'application a terminé avec un court délai.

Espérons que cela aidera tous ceux qui font face au même problème.

Edit: La raison était que, dans ma méthode activity.onPause() j'ai appelé glSurfaceView.onPause() tout a été bloqué de onDraw() le fil rendu.