Em um serviço Android, criei thread (s) para executar alguma tarefa em segundo plano.
Eu tenho uma situação em que um thread precisa postar determinada tarefa na fila de mensagens do thread principal, por exemplo: a Runnable
.
Existe uma maneira de obter Handler
do segmento principal e pós Message
/ Runnable
a ele do meu outro segmento?
Obrigado,
Respostas:
NOTA: Esta resposta recebeu tanta atenção que preciso atualizá-la. Desde que a resposta original foi postada, o comentário de @dzeikei recebeu quase tanta atenção quanto a resposta original. Então, aqui estão duas soluções possíveis:
1. Se o encadeamento em segundo plano tiver uma referência a um
Context
objeto:Verifique se os threads de trabalho em segundo plano têm acesso a um objeto de Contexto (pode ser o contexto de Aplicativo ou o contexto de Serviço). Em seguida, basta fazer isso no thread de trabalho em segundo plano:
2. Se o encadeamento em segundo plano não tiver (ou precisar) de um
Context
objeto(sugerido por @dzeikei):
fonte
Handler
(ou usar aHandler.Callback
interface), seuhandleMessage()
método SOMENTE será chamado para mensagens postadas usando seu manipulador. O thread principal está usando um manipulador diferente para postar / processar mensagens, para que não haja conflito.Handler mainHandler = new Handler(Looper.getMainLooper());
new Runnable(){@Override public void run() {....}};
Como um comentarista abaixo apontou corretamente, essa não é uma solução geral para serviços, apenas para threads iniciados a partir de sua atividade (um serviço pode ser esse segmento, mas nem todos). Sobre o tópico complicado da comunicação de atividade de serviço, leia toda a seção Serviços do documento oficial - é complexo, portanto vale a pena entender o básico: http://developer.android.com/guide/components/services.html #Notifications
O método abaixo pode funcionar nos casos mais simples.
Se eu entendi corretamente, você precisa de algum código para ser executado no thread da GUI do aplicativo (não consigo pensar em nada mais chamado thread "principal"). Para isso, existe um método em
Activity
:Doc: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29
Espero que seja isso que você está procurando.
fonte
Service
. Você não pode usarrunOnUiThread()
em aService
. Esta resposta é enganosa e não aborda a pergunta feita.Existe outra maneira simples, se você não tiver acesso ao contexto.
1) Crie um manipulador a partir do looper principal:
2) Implemente uma interface Runnable:
3) Publique o seu Runnable no uiHandler:
Isso é tudo ;-) Divirta-se com os tópicos, mas não se esqueça de sincronizá-los.
fonte
Se você executar código em um encadeamento, por exemplo, adiando alguma ação, precisará invocar a
runOnUiThread
partir do contexto. Por exemplo, se seu código estiver dentro daMainActivity
classe, use o seguinte:Se o seu método puder ser chamado a partir do main (thread da UI) ou de outros threads, você precisará de uma verificação como:
fonte
Service
. Você não pode usarrunOnUiThread()
em aService
.Activity
documentação,runOnUiThread()
é um método deActivity
. Não é um método deService
, portanto, você não pode usá-lo. O que poderia ser mais claro do que isso?Um bloco de código condensado é o seguinte:
Isso não envolve passar a referência de atividade ou a referência de aplicativo.
Equivalente de Kotlin:
fonte
Versões do Kotlin
Quando você estiver em uma atividade , use
Quando você tem um contexto de atividade , o mContext então usa
Quando você estiver em algum lugar onde não há contexto disponível , use
fonte
runOnUiThread(){...}
A maneira mais simples, especialmente se você não tiver um contexto, se estiver usando o RxAndroid, poderá:
fonte
Código Kotlin mais preciso usando manipulador:
fonte
Um método que posso pensar é o seguinte:
1) Deixe a interface do usuário vincular ao serviço.
2) Exponha um método como o abaixo,
Binder
que registra seuHandler
:3) No thread da interface do usuário, chame o método acima após a ligação ao serviço:
4) Use o manipulador no encadeamento do serviço para postar sua tarefa:
fonte
HandlerThread
é a melhor opção para threads Java normais no Android.requestHandler
post
umaRunnable
tarefa emrequestHandler
Comunicação com o Thread da UI de
HandlerThread
Handler
withLooper
para main:responseHandler
e substituahandleMessage
Runnable
tarefa de outra Thread (HandlerThread
neste caso), chamadasendMessage
emresponseHandler
sendMessage
chamada deste resultado dehandleMessage
inresponseHandler
.Message
e processá-lo, atualizar a interface do usuárioExemplo : atualização
TextView
com dados recebidos de um serviço da web. Como o serviço da web deve ser chamado em um segmento que não seja da interface do usuário, criadoHandlerThread
para a Operação de Rede. Depois de obter o conteúdo do serviço da Web, envie uma mensagem para o manipulador de thread principal (UI Thread) eHandler
ele manipulará a mensagem e atualizará a UI.Código de amostra:
Artigos úteis:
manipuladores-e-por-que-você-deveria-estar-usando-seus-aplicativos-android
android-looper-handler-handlerthread-i
fonte
Sei que essa é uma pergunta antiga, mas me deparei com uma linha principal de thread principal usada no Kotlin e no Java. Essa pode não ser a melhor solução para um serviço, mas chamar alguma coisa que altere a interface do usuário dentro de um fragmento é extremamente simples e óbvio.
Java (8):
Kotlin:
fonte
Siga este método. Usando essa maneira, você pode simplesmente atualizar a interface do usuário a partir de um thread em segundo plano. O runOnUiThread funciona no thread principal (UI). Eu acho que esse trecho de código é menos complexo e fácil, principalmente para iniciantes.
no caso de um serviço
crie um manipulador no oncreate
então use-o assim
fonte
para Kotlin, você pode usar as corountines Anko :
atualizar
descontinuada
fonte
O mais útil é fazer o seguinte:
E depois:
fonte
Isso também pode funcionar em uma classe de serviço sem problemas.
fonte
Com o Kotlin, é assim dentro de qualquer função:
fonte
Activity
.