Je suis tombé sur les deux Handlers et runOnUiThread concepts. Mais pour moi, il semble toujours y avoir un doute quant aux faits sur lesquels ils diffèrent exactement.
Ils sont tous deux destinés à effectuer des actions d'interface utilisateur à partir d'un thread en arrière-plan. Mais quels sont les facteurs à prendre en compte lorsque nous choisissons parmi les deux méthodes.
Par exemple, considérons une Runnable
Thread
qui effectue un service Web en arrière-plan et je souhaite maintenant mettre à jour l'interface utilisateur.
Quel serait le meilleur moyen de mettre à jour mon interface utilisateur? Devrais-je choisir Handler
ou runOnUiThread
?
Je sais toujours que je pourrais utiliser un AsyncTask
et utiliser onPostExecute
. Mais je veux juste connaître la différence.
Activity.runOnUiThread () est un cas particulier de plus générique Gestionnaires . Avec Handler
, vous pouvez créer votre propre requête d'événement dans votre propre thread. Utiliser Handlers
instancié avec constructeur par défautnot signifie "le code sera exécuté sur le thread d'interface utilisateur" en général. Par défaut, les gestionnaires liés à Thread
à partir desquels ils ont été instanciés.
Pour créer Handler
dont la liaison avec le thread UI (principal) est garantie, vous devez créer un objet Handler
lié à Main Looper comme ceci:
Handler mHandler = new Handler(Looper.getMainLooper());
De plus, si vous vérifiez l’implémentation de la méthode runOnuiThread()
, elle utilise Handler
pour faire les choses suivantes:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Comme vous pouvez le constater à partir de l'extrait de code ci-dessus, Runnable action
sera exécuté immédiatement si runOnUiThread()
est appelé à partir du thread d'interface utilisateur. Sinon, il le postera dans la Handler
, qui sera exécutée ultérieurement.
Les gestionnaires ont de nombreux travaux comme message en passant et des mises à jour fréquentes de l'interface utilisateur si vous démarrez Un thread pour toute tâche en cours d'exécution. de nombreuses applications comme le chat bluetooth, le chat wifi ... et le gestionnaire ont comme méthode PostDelay et PostAtTime, qui vous permettent de jouer avec n'importe quelle vue pour animer et modifier la visibilité, etc.
Vous devez regarder dans cette
http://developer.Android.com/guide/components/processes-and-threads.html
http://developer.Android.com/tools/testing/activity_testing.html
Suite à la réponse de HitOdessit.
Vous pouvez créer une classe comme celle-ci.
public class Global{
private static Handler mHandler = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable action){
mHandler.post(action);
}
}
Et puis appelez ça comme ça.
Global.runOnUiThread(new Runnable(){
//Your code
});
Et cela peut être exécuté de n’importe où (où vous avez accès à votre classe Global).
Les gestionnaires étaient à l’origine (API niveau 1) de faire des choses, puis AsycTask
(API niveau 3) ont été introduits, avec un accent plus marqué sur l’utilisation de runOnUIThread
(API niveau 1). Dans la mesure du possible, évitez d’utiliser des gestionnaires et préférez les deux autres en fonction de vos besoins.
Quel serait le meilleur moyen de mettre à jour mon interface utilisateur? Devrais-je choisir Handler ou runOnUiThread?
Si votre Runnable
a besoin de mettre à jour l'interface utilisateur, publiez-la sur runOnUiThread
.
Mais il n'est pas toujours possible de publier Runnable
sur le fil de l'interface utilisateur.
Pensez au scénario dans lequel vous souhaitez exécuter Opération réseau/IO ou appeler un service Web. Dans ce cas, vous ne pouvez pas publier Runnable
dans le thread UI. Il va jeter Android.os.NetworkOnMainThreadException
Ce type de Runnable
doit être exécuté sur un autre thread tel que HandlerThread . Une fois votre opération terminée, vous pouvez publier le résultat dans UI Thread en utilisant Handler
, associé à UI Thread.
public void onClick(View view) {
// onClick on some UI control, perform Network or IO operation
/* Create HandlerThread to run Network or IO operations */
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
/* Create a Handler for HandlerThread to post Runnable object */
Handler requestHandler = new Handler(handlerThread.getLooper());
/* Create one Handler on UI Thread to process message posted by different thread */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
requestHandler.post(r1);
requestHandler.post(r2);
}
class NetworkRunnable implements Runnable{
String url;
Handler uiHandler;
public NetworkRunnable(String url,Handler uiHandler){
this.url = url;
this.uiHandler=uiHandler;
}
public void run(){
try {
Log.d("Runnable", "Before IO call");
URL page = new URL(url);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
/* Send result back to UI Thread Handler */
uiHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
}