Comment vérifier si le thread actuel n'est pas le thread principal

Réponses:

709
Looper.myLooper() == Looper.getMainLooper()

si cela retourne vrai, alors vous êtes sur le fil de l'interface utilisateur!

Charnel
la source
Comment exécutez-vous ce code dans junit?
John Sardinha
123

vous pouvez utiliser le code ci-dessous pour savoir si le thread actuel est UI / Main thread ou non

if(Looper.myLooper() == Looper.getMainLooper()) {
   // Current Thread is Main Thread.
}

ou vous pouvez également l'utiliser

if(Looper.getMainLooper().getThread() == Thread.currentThread()) {
   // Current Thread is Main Thread.
}

Voici une question similaire

AAnkit
la source
8
Doit-on considérer ce dernier comme l'option la plus sûre car il n'y a aucune garantie qu'un thread arbitraire soit associé à un Looper (en supposant que le thread principal est toujours associé à un Looper)?
Janus Varmarken
Looper.myLooper()retournera null si le thread n'est pas associé à un Looper. Les deux sont donc sûrs et ont le même résultat, mais le premier est un peu plus lent pendant qu'il recherche dans une carte pour trouver le looper et son thread associé et faire d'autres choses.
Saeed Masoumi
59

Le meilleur moyen est le moyen le plus clair et le plus robuste: *

Thread.currentThread().equals( Looper.getMainLooper().getThread() )

Ou, si la plate-forme d'exécution est de niveau API 23 (Marshmallow 6.0) ou supérieur:

Looper.getMainLooper().isCurrentThread()

Voir l' API Looper . Notez que l'appel Looper.getMainLooper()implique la synchronisation (voir la source ). Vous souhaiterez peut-être éviter la surcharge en stockant la valeur de retour et en la réutilisant.

   * crédit greg7gkb et 2cupsOfTech

Michael Allan
la source
Qu'entendez-vous par «sous API 23 ou supérieure»? Cela n'a pas beaucoup de sens pour moi .. Aussi la même réponse exacte a été postée par AAnkit, ci-dessous ..
Mike
@Mike Merci, j'ai corrigé le bit API. AAnkit favorise en fait Looper.myLooper() == Looper.getMainLooper(), ce qui, je pense, est moins clair. Je crédite greg7gkb.
Michael Allan
1
cela devrait-il être une comparaison avec == ou equals () car Android Studio émet un avertissement?
2cupsOfTech
@ 2cupsOfTech À la réflexion, c'est un bon conseil. Actuellement, les deux tests sont les mêmes au moment de l'exécution, car Thread ne remplace pas equals, et revient donc à ==, mais cela pourrait changer à l'avenir. J'ai donc corrigé la réponse.
Michael Allan
25

Résumant les solutions, je pense que c'est la meilleure:

boolean isUiThread = VERSION.SDK_INT >= VERSION_CODES.M 
    ? Looper.getMainLooper().isCurrentThread()
    : Thread.currentThread() == Looper.getMainLooper().getThread();

Et, si vous souhaitez exécuter quelque chose sur le thread d'interface utilisateur, vous pouvez utiliser ceci:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});
développeur android
la source
6

Tu peux vérifier

if(Looper.myLooper() == Looper.getMainLooper()) {
   // You are on mainThread 
}else{
// you are on non-ui thread
}
Lovekush Vishwakarma
la source
2

Permettez-moi de faire une préface à ceci: j'ai reconnu que ce post avait le tag 'Android', cependant, ma recherche n'avait rien à voir avec 'Android' et c'était mon meilleur résultat. À cette fin, pour les utilisateurs non Android SO Java qui arrivent ici, n'oubliez pas:

public static void main(String[] args{
    Thread.currentThread().setName("SomeNameIChoose");
    /*...the rest of main...*/
}

Après avoir défini cela, ailleurs dans votre code, vous pouvez facilement vérifier si vous êtes sur le point d'exécuter sur le thread principal avec:

if(Thread.currentThread().getName().equals("SomeNameIChoose"))
{
    //do something on main thread
}

Un peu gêné j'avais cherché avant de m'en souvenir, mais j'espère que cela aidera quelqu'un d'autre!

ThatOneGuy
la source
1

vous pouvez le vérifier dans android ddms logcat où l'identifiant du processus sera le même mais l'identifiant du thread sera différent.

Vishwanath.M
la source
1

Xamarin.Androidport: ( C#)

public bool IsMainThread => Build.VERSION.SdkInt >= BuildVersionCodes.M
    ? Looper.MainLooper.IsCurrentThread
    : Looper.MyLooper() == Looper.MainLooper;

Usage:

if (IsMainThread) {
    // you are on UI/Main thread
}
Mehdi Dehghani
la source
-6

Vous pouvez essayer Thread.currentThread (). IsDaemon ()

Shailendra Singh
la source
Je ne suis pas sûr que le thread d'interface utilisateur soit un démon mais je vous croirai sur celui-ci. Mais comment allez-vous faire la différence avec un thread démon que je pourrais (mais ne devrais pas) créer.
AxelH
J'ai testé dans mon application web, cela montre que le thread UI est un thread Daemon. J'ai mis quelques points d'arrêt de débogage dans l'environnement d'éclipse et l'ai vérifié. Détail du fil affiché comme fil [http-bio-8080-exec-7,5, main]. Cliqué sur certaines pages de l'interface utilisateur et vérifié le point de débogage.
Shailendra Singh
De plus, même si le nom du thread détaille son affichage «principal», mais appeler setDaemon (true) sur l'objet thread le rendra démon.
Shailendra Singh
Vous n'avez pas lu la bonne partie ... Je ne doutais pas (complètement) qu'il s'agissait d'un Daemon, je disais que vous ne pouvez pas faire la différence avec un autre thread Daemon comme celui-ci.
AxelH
Autrement dit: un thread principal peut être un thread démon, mais tous les threads démon ne sont pas le thread principal. (Identifier le fil principal est ce qui est demandé ici.)