Como verificar se o segmento atual não é o principal

392

Preciso verificar se o segmento executando um determinado pedaço de código é o segmento principal (UI) ou não. Como posso conseguir isso?

Charlie-Blake
fonte
exemplo para demonstrar com exemplos de rosca code2concept.blogspot.in/2015/02/...
nitesh

Respostas:

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

se isso retornar true, você estará no thread da interface do usuário!

Carnal
fonte
Como você executa esse código em junho?
John Sardinha
123

você pode usar o código abaixo para saber se o thread atual é UI / Main thread ou não

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

ou você também pode usar isso

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

Aqui está uma pergunta semelhante

AAnkit
fonte
8
Deve-se considerar o último como a opção mais segura, pois não há garantia de que qualquer encadeamento arbitrário esteja associado a um Looper (assumindo que o encadeamento principal esteja sempre associado a um looper)?
Janus Varmarken
Looper.myLooper()retornará nulo se o encadeamento não estiver associado a um Looper. Portanto, ambos são seguros e têm o mesmo resultado, mas o primeiro é um pouco mais lento enquanto ele pesquisa dentro de um mapa para descobrir o looper e seu thread associado e fazer outras coisas.
Saeed Masoumi
59

A melhor maneira é a maneira mais clara e robusta: *

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

Ou, se a plataforma de tempo de execução for o nível 23 da API (Marshmallow 6.0) ou superior:

Looper.getMainLooper().isCurrentThread()

Veja a API do Looper . Observe que a chamada Looper.getMainLooper()envolve sincronização (consulte a fonte ). Você pode evitar a sobrecarga armazenando o valor de retorno e reutilizando-o.

   * credit greg7gkb e 2cupsOfTech

Michael Allan
fonte
O que você quer dizer com "na API 23 ou superior"? Isso não faz muito sentido para me..Also a mesma resposta exata foi publicado por AAnkit, abaixo ..
Mike
@ Mike Obrigado, eu corrigi o bit API. AAnkit realmente é favorável Looper.myLooper() == Looper.getMainLooper(), o que eu acho que é menos claro. Eu credito greg7gkb.
Michael Allan
11
deve ser uma comparação com == ou igual a (), pois o Android Studio gera um aviso?
Juls
@ 2cupsOfTech No segundo pensamento, esse é um bom conselho. Atualmente, os dois testes são os mesmos em tempo de execução porque o Thread não substitui equalse, portanto, volta a ser ==, mas isso pode mudar no futuro. Então eu corrigi a resposta.
Michael Allan
25

Resumindo as soluções, acho que é a melhor:

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

E, se você deseja executar algo no thread da interface do usuário, pode usar o seguinte:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});
desenvolvedor android
fonte
6

Você pode checar

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

Permitam-me que antecipe isso com: Eu reconheci que este post tem a tag 'Android', no entanto, minha pesquisa não teve nada a ver com 'Android' e esse foi o meu principal resultado. Para esse fim, para os usuários SO Java que não são do Android que chegam aqui, não se esqueça:

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

Depois de definir isso, em outro lugar do seu código, você pode verificar facilmente se está prestes a executar no thread principal com:

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

Um pouco envergonhado, eu tinha procurado antes de lembrar isso, mas espero que ajude alguém!

ThatOneGuy
fonte
1

você pode verificá-lo no android ddms logcat, onde a identificação do processo será a mesma, mas a identificação da thread será diferente.

Vishwanath.M
fonte
1

Xamarin.Androidporta: ( C#)

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

Uso:

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

Você pode tentar Thread.currentThread (). IsDaemon ()

Shailendra Singh
fonte
Não tenho certeza de que o thread da interface do usuário seja um daemon, mas acreditarei em você. Mas como você fará a diferença com um Daemon Thread que eu poderia (mas não deveria) criar.
AxelH
Eu testei no meu aplicativo da web, ele mostra que o thread da interface do usuário é um thread do Daemon. Coloquei alguns pontos de interrupção de depuração no ambiente eclipse e verifiquei. Detalhes do segmento mostrados como Tópico [http-bio-8080-exec-7,5, principal]. Clicou em algumas páginas da interface do usuário e verificou o ponto de depuração.
Shailendra Singh
Além disso, mesmo que nos detalhes do nome do encadeamento seja exibido 'main', mas chamar setDaemon (true) no objeto de encadeamento o tornará daemon.
Shailendra Singh
Você não leu a parte boa ... Eu não estava duvidando (completamente) de ser um Daemon, estava dizendo que você não pode fazer as diferenças com outro segmento do Daemon como este.
AxelH
Em outras palavras: um encadeamento principal pode ser um encadeamento daemon, mas nem todos os encadeamentos daemon são o encadeamento principal. (Identificar o segmento principal é o que está sendo pedido aqui.)