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!


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


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


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
    }
});

6

Możesz sprawdzić

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

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!


1

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


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
}

-6

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


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.)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.