Jak sprawdzić, czy bieżący wątek nie jest głównym wątkiem

Odpowiedzi:

707
Looper.myLooper() == Looper.getMainLooper()

jeśli to zwraca wartość true, oznacza to, że jesteś w wątku interfejsu użytkownika!

Cielesny
źródło
Jak uruchomić ten kod w programie junit?
John Sardinha
122

możesz użyć poniższego kodu, aby dowiedzieć się, czy bieżący wątek to interfejs użytkownika / główny wątek, czy nie

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

lub możesz także tego użyć

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

Oto podobne pytanie

AAnkit
źródło
8
Czy należy uznać to drugie za bezpieczniejszą opcję, ponieważ nie ma gwarancji, że dowolny Loop jest powiązany z Looper (zakładając, że główny wątek jest zawsze powiązany z Looper)?
Janus Varmarken
Looper.myLooper()zwróci null, jeśli wątek nie jest powiązany z Looper. Oba są więc bezpieczne i mają ten sam wynik, ale pierwszy jest nieco wolniejszy, gdy przeszukuje mapę, aby znaleźć looper i związany z nim wątek i zrobić kilka innych rzeczy.
Saeed Masoumi
59

Najlepszy sposób to najczystszy, najsolidniejszy sposób: *

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

Lub, jeśli platforma uruchomieniowa ma interfejs API na poziomie 23 (Marshmallow 6.0) lub nowszym:

Looper.getMainLooper().isCurrentThread()

Zobacz Looper API . Pamiętaj, że wywoływanie Looper.getMainLooper()wymaga synchronizacji (patrz źródło ). Możesz uniknąć kosztów ogólnych, przechowując wartość zwracaną i ponownie ją wykorzystując.

   * kredyt greg7gkb i 2cupsOfTech

Michael Allan
źródło
Co rozumiesz przez „pod API 23 lub wyższym”? To nie ma dla mnie większego sensu. Dokładnie taką samą odpowiedź opublikował AAnkit poniżej…
Mike
@ Mike Dzięki, naprawiłem bit API. AAnkit faktycznie sprzyja Looper.myLooper() == Looper.getMainLooper(), co moim zdaniem jest mniej jasne. Kredytuję greg7gkb.
Michael Allan,
1
czy powinno to być porównanie z == lub równa się (), ponieważ Android Studio wyświetla ostrzeżenie?
2cupsOfTech
@ 2cupsOfTech Na drugiej myśli, to dobra rada. Obecnie oba testy są takie same w środowisku wykonawczym, ponieważ Wątek nie zastępuje equalsi dlatego wraca do ==, ale może się to zmienić w przyszłości. Więc poprawiłem odpowiedź.
Michael Allan,
25

Podsumowując rozwiązania, myślę, że to najlepsze:

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

A jeśli chcesz uruchomić coś w wątku interfejsu użytkownika, możesz użyć tego:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});
programista Androida
źródło
6

Możesz sprawdzić

if(Looper.myLooper() == Looper.getMainLooper()) {
   // You are on mainThread 
}else{
// you are on non-ui thread
}
Lovekush Vishwakarma
źródło
2

Pozwólcie, że przedstawię to następująco: Potwierdziłem, że ten post ma tag „Android”, jednak moje wyszukiwanie nie miało nic wspólnego z „Androidem” i to był mój najlepszy wynik. W tym celu w przypadku użytkowników Java SO non-Android lądujących tutaj nie zapomnij o:

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

Po ustawieniu tego w innym miejscu kodu możesz łatwo sprawdzić, czy zamierzasz wykonać główny wątek za pomocą:

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

Trochę zawstydzony, szukałem, zanim to zapamiętałem, ale mam nadzieję, że pomoże to komuś innemu!

ThatOneGuy
źródło
1

możesz to zweryfikować w Android ddms logcat, gdzie identyfikator procesu będzie taki sam, ale identyfikator wątku będzie inny.

Vishwanath.M
źródło
1

Xamarin.Androidport: ( C#)

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

Stosowanie:

if (IsMainThread) {
    // you are on UI/Main thread
}
Mehdi Dehghani
źródło
-6

Możesz wypróbować Thread.currentThread (). IsDaemon ()

Shailendra Singh
źródło
Nie jestem pewien, czy wątek interfejsu użytkownika jest demonem, ale w to uwierzę. Ale w jaki sposób zrobisz różnicę za pomocą wątku demona, który mógłbym (ale nie powinien) stworzyć.
AxelH
Przetestowałem w mojej aplikacji internetowej, pokazuje, że wątek interfejsu użytkownika jest wątkiem Daemon. Umieściłem niektóre punkty przerwania debugowania w środowisku Eclipse i zweryfikowałem je. Szczegóły wątku pokazane jako wątek [http-bio-8080-exec-7,5, main]. Kliknąłem niektóre strony interfejsu użytkownika i sprawdziłem punkt debugowania.
Shailendra Singh,
Ponadto, nawet jeśli w szczegółach nazwy wątku wyświetlana jest „główna”, ale wywołanie setDaemon (true) na obiekcie wątku spowoduje, że będzie on demonem.
Shailendra Singh,
Nie przeczytałeś dobrej części ... Nie wątpiłem (całkowicie) o to, że jest Daemonem, mówiłem, że nie możesz robić różnic z innym wątkiem Daemona takim jak ten.
AxelH
Innymi słowy: główny wątek może być wątkiem demona, ale nie wszystkie wątki demona są wątkiem głównym. (O to tutaj pyta się o główny wątek.)