Tempo de leitura: 8 minutos
Você está sentado quieto? Indo dirigir
Escreva na frente
O conteúdo compartilhado hoje é uma análise aprofundada do mecanismo de mensagem do Android.Algumas pessoas perguntaram, algumas funções podem ser usadas? Por que analisar o código-fonte subjacente? O que Xiaolu diz a você hoje é que muitos projetos de código aberto não precisam mais de nós para construir rodas, e como é estúpido reconstruí-las. No entanto, o código-fonte subjacente do Android e a realização de algumas funções nos permitem aprender o padrão subjacente e a implementação lógica.
A coisa mais importante sobre aprender programação é o pensamento lógico.Mesmo se você pode alcançar qualquer função, você não pode fazer nada com pouca habilidade de pensamento lógico. Sua capacidade de raciocínio lógico é fraca e sua altura foi determinada na rota técnica.
Mecanismo de mensagem do Android
O mecanismo de mensagem do Android significa principalmente que a operação do Handler precisa do suporte do MessageQueue e do Looper subjacentes.
(1) A tradução chinesa de MessageQueue é uma fila de mensagens. Fornece inserção e exclusão de trabalho externamente na forma de uma fila. Embora seja chamada de fila de mensagens, a estrutura de armazenamento interno não é uma fila real, mas uma estrutura de dados de lista vinculada individualmente para armazenar a lista de mensagens.
(2) A tradução chinesa do Looper é loop, nós o chamamos de loop de mensagem. Como MessageQueue é apenas uma unidade de armazenamento, ela não processará mensagens. O looper compensa esta função. Looper irá procurar por novas mensagens em um loop infinito e processar as mensagens se houver, caso contrário, ele esperará para sempre.
Mapa mental de aprendizagem:
Os mapas mentais em artigos futuros são cuidadosamente organizados por Xiaolu para todos, de modo que cada artigo compartilhado tenha uma estrutura clara, o que conduz à revisão e organização.
1. Visão geral do mecanismo de mensagem Android
O mecanismo de mensagem do Android se refere principalmente ao mecanismo operacional de Handler e ao processo de trabalho de MessageQueue e Looper anexado ao Handler. A principal função do Handler é mudar uma tarefa para um thread especificado para execução.
Visão geral
(1) Pensando: Por que o Android fornece essa função?
Resposta: Como o Android estipula que o thread de IU só pode ser acessado no thread principal, se a IU for acessada no thread filho, o programa lançará uma exceção.
(2) Código-fonte: Depois de verificar o código-fonte, o método checkThread () verifica se a UI de atualização está atualizada no thread principal e lança uma mensagem de exceção para lembrar o desenvolvedor (acredito que isso tenha sido encontrado no desenvolvimento).
(3) Processo: devido às restrições acima, isso requer que os desenvolvedores atualizem a IU no thread principal, mas o Android também recomenda não fazer um trabalho muito demorado no thread principal, caso contrário, o aplicativo não responderá ao ANR. Considerando esta situação, quando extraímos algumas informações do servidor e as exibimos na IU, faremos o trabalho de pull no thread filho. Após a conclusão do pull, a IU não pode ser atualizada diretamente no thread filho. Sem o Handler, then we Na verdade, não há como alternar o trabalho de acesso à IU para o thread principal para execução. Portanto, a principal razão pela qual o sistema nos fornece o Handler é resolver a contradição de que a IU não pode ser acessada no thread filho.
(4) Pergunta:
① 为什么不能再子线程中更新 UI?
答 : 因为 Android 的 UI 控件不是线性安全的。如果在多线程中并发的访问可能会导致 UI 控件处于不可预期的状态。
② 为什么不对 UI 控件的访问加上锁机制呢?
答 :首先,加上锁机制会让访问 UI 变的复杂,其次锁机制会降低 UI 的访问效率,因为锁机制会阻塞某些线程的执行。
A maneira mais simples e eficiente é usar um modelo de thread único para lidar com as operações da IU. Você só precisa alternar o thread de execução do acesso à IU por meio de Handlerr.
Como funciona o manipulador
Quando o Handler é criado, o Looper atual será usado para construir o sistema de loop de mensagem interno.Se não houver nenhum Looper atualmente, um erro será relatado.
Como resolver os problemas acima? Dois métodos:
① Basta criar o Looper para o tópico atual.
② Também é possível criar um Handler no thread do Looper.
princípio de trabalho
(1) Processo de criação do Handler: Depois que o Handler é criado, o MessageQueue interno e o Looper trabalham juntos com o Handler e, em seguida, um Runnable é entregue ao Looper dentro do Handler para processamento por meio do método post do Handler; também pode ser processado por meio o método send do Handler envia uma mensagem, que também é processada pelo Looper. Na verdade, o método Post é finalmente completado pelo método send.
(2) O processo de trabalho do método send: quando o método send do Handler é chamado, ele chamará o método enqueueMessage de MessageQueue para colocar a mensagem na fila de mensagens, e então o Looper processará a mensagem quando encontrar um novo mensagem e, finalmente, o Runnable da mensagem ou o método handlerMessage de Handler será chamado.
Dois, a análise do mecanismo de mensagem do Android
Como funciona a fila de mensagens
A fila de mensagens no Android se refere principalmente a MessageQueue, MessageQueue inclui principalmente duas operações: inserir e excluir. A implementação interna da fila de mensagens não é uma fila. Na verdade, a fila de mensagens é mantida por meio da estrutura de dados de uma lista unida individualmente. A lista unida individualmente tem vantagens na inserção e exclusão.
① Inserir (enqueueMessage): insere uma mensagem na fila de mensagens. (A implementação do código-fonte é a inserção de uma lista unida)
② Excluir (próximo): Retire uma mensagem da fila de mensagens e remova-a da fila de mensagens. (O próximo é um método de loop infinito, a fila de mensagens é bloqueada sem informações e a lista unicamente vinculada é excluída quando uma nova mensagem chega)
Como funciona o Lopper
Looper desempenha a função de loop de mensagem no mecanismo de mensagem do Android. Sua função é verificar constantemente se há novas mensagens do MessageQueue. Se houver mensagens, elas serão processadas imediatamente e, se não houver mensagens, serão bloqueadas .
(1) Método de construção Looper
① Crie uma fila de mensagens MessageQueue.
② Salve o objeto do segmento atual.
(2) Como criar Looper para um tópico
(Trabalho de manuseio requer Looper, sem Looper, um erro será relatado)
① 通过 Looper.prepare() 方法为线程创建一个 Looper 。
② 通过 Looper.loop() 方法来开启消息循环。
(3) Outra maneira de criar tópicos
① 主线程 Looper 的获取。 Looper 这个方法主要给线程也就是 ActivityThread 创建 Looper 使用的,本质也是通过 prepare 来实现的,由于主线程的 Looper 比较特殊,所以 Looper 提供了一个 getMainLopper 的方法获取主线程的 Looper。
② Looper 的退出。****Looper 提供了两个方法:quit 方法和 quitSafely 方法。
A diferença entre os dois: Sair sai do Looper diretamente.
E quitSafely apenas define uma marca de saída e sai após processar as mensagens na fila de mensagens.
(4) O princípio de realização do método Looper.loop ()
loop 是一个死循环,唯一能跳出循环的方法就是 MessageQueue 的 next 方法返回了 null。当 Looper 的 quit 方法被调用时,MessageQueue 的 quit 方法或者 quitSafely 方法就会通知消息队列退出,当消息队列被标记为退出状态时,next 就会返回一个 null。Looper 是必须退出的,否则 loop 会永远循环下去。
O método de loop chamará o próximo método de MessageQueue para obter a mensagem.Se o MessageQueue não tiver mensagens, o próximo estará em um estado de bloqueio e o método de loop também estará em um estado de bloqueio.
Explique o princípio de funcionamento do Handler em detalhes
A principal tarefa do Handler é enviar e receber mensagens. A mensagem pode ser enviada através de uma série de métodos de postagem e de uma série de métodos de envio.A série de métodos de postagem é finalmente realizada através de uma série de métodos de envio.
Código:
1public class HandlerActivity extends Activity {
2
3 @Override
4 protected void onCreate(@Nullable Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 setContentView(R.layout.activity_main);
7
8 //开启线程
9 handler();
10 }
11 //主线程
12 Handler handler = new Handler(){
13
14 @Override
15 public void handleMessage(Message msg) {
16 super.handleMessage(msg);
17 switch (msg.what) {
18 case 1:
19 // 获取Message里面的复杂数据
20 Bundle date = new Bundle();
21 date = msg.getData();
22 String name = date.getString("name");
23 int age = date.getInt("age");
24 String sex = date.getString("sex");
25 //这里是主线程,可进行对UI的更新
26 textView.setText(name)
27 }
28 }
29 };
30
31 //子线程
32 public void handler(){
33 new Thread(new Runnable() {
34 @Override
35 public void run() {
36 Message message = new Message();
37 message.what = 1;
38
39 // Message对象保存的数据是Bundle类型的
40 Bundle data = new Bundle();
41 data.putString("name", "李文志");
42 data.putInt("age", 18);
43 data.putString("sex", "男");
44 // 把数据保存到Message对象中
45 message.setData(data);
46 // 使用Handler对象发送消息
47 handler.sendMessage(message);
48 }
49 }).start();
50 }
51}
enviar mensagens
Por meio da análise do código-fonte, o processo de Handler de enviar uma mensagem consiste apenas em inserir uma parte da informação na fila de mensagens, e o próximo método de MessageQueue retornará essa informação ao Looper, e o Looper irá processá-la imediatamente após receber o mensagem, e Looper irá entregá-la para Handler para processar a mensagem, o método dispatchMessage de Handler será chamado e, em seguida, Handler entrará no estágio de processamento de mensagem.
Processamento de mensagens
Uma análise aprofundada do código-fonte de dispatchMessage, o Handler processa a mensagem da seguinte maneira:
① Primeiro verifique se o retorno de chamada de Message é nulo.Se não for nulo, processe a mensagem através de handlerCallback. (O retorno de chamada da mensagem é um objeto Runnable d, que é na verdade o parâmetro Runnable passado pelo método post)
② Em segundo lugar, verifique se mCallback é nulo.Se não for nulo, chame o método handlerMessage de mCallback para processar a mensagem. O retorno de chamada é uma interface.
③ Por meio do Callback, podemos usar os seguintes métodos para criar objetos Handle.
1Handler handler = new Handler(callback);
O significado desta criação é criar uma instância, mas não precisa derivar uma subclasse de Handler.
④ No entanto, em nosso desenvolvimento diário, frequentemente derivamos uma subclasse de Handler e sobrescrevemos seu método handleMessage para processar mensagens específicas.Se você não quiser criar uma subclasse derivada, você pode usar Callback.
Loop de mensagem do tópico principal
O thread principal do Android é ActivityThread. O método de entrada do thread principal é main. No método principal, o sistema usará Looper.prepareMainLooper (); para criar o Looper e MessageQueue do thread principal e usar Looper.loop ( ) para abrir a mensagem do ciclo do thread principal.
Depois que o loop de mensagem do thread principal é iniciado, ActivityThread também precisa de um Handler para interagir com a fila de mensagens.Este Handler é ActivityThread.H. ActivityThread se comunica entre processos por meio de ApplicationThread e AMS. Depois que o AMS conclui a solicitação de ActvityThread por meio da comunicação entre processos, ele chamará de volta o método Binder em ApplicationThread e, em seguida, ApplicationThread enviará uma mensagem para H, e H mudará a lógica em ApplicationThread para ActivityThread ao receber a mensagem. Execute no meio, ou seja, mude para o thread principal para execução. Este processo é o modelo de loop de mensagem do thread principal.