È possibile comprendere meglio cos'è Looper nel contesto del framework GUI. Looper è fatto per fare 2 cose.
1) Looper trasforma un thread normale , che termina quando ritorna il suo metodo run (), in qualcosa di continuo finché l'app Android non è in esecuzione , che è necessario nel framework GUI (tecnicamente, termina ancora quando restituisce il metodo run (). chiarire cosa intendo di seguito).
2) Looper fornisce una coda in cui vengono accodati i lavori da eseguire, che è anche necessario nel framework della GUI.
Come forse saprai, quando viene lanciata un'applicazione, il sistema crea un thread di esecuzione per l'applicazione, chiamato "main", e le applicazioni Android normalmente vengono eseguite interamente su un singolo thread per impostazione predefinita, il "thread principale". Ma il thread principale non è un thread speciale segreto . È solo un normale thread simile ai thread creati con il new Thread()
codice, il che significa che termina quando ritorna il suo metodo run ()! Pensa all'esempio seguente.
public class HelloRunnable implements Runnable {
public void run() {
System.out.println("Hello from a thread!");
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Ora applichiamo questo semplice principio alle app Android. Cosa succederebbe se un'app Android funzionasse su un thread normale? Un thread chiamato "main" o "UI" o qualunque cosa avvii l'applicazione e disegna tutta l'interfaccia utente. Quindi, la prima schermata viene mostrata agli utenti. Così quello che ora? Il thread principale termina? No, non dovrebbe. Dovrebbe aspettare che gli utenti facciano qualcosa, giusto? Ma come possiamo ottenere questo comportamento? Bene, possiamo provare con Object.wait()
oThread.sleep()
. Ad esempio, il thread principale termina il lavoro iniziale per visualizzare la prima schermata e dorme. Si sveglia, il che significa interrotto, quando viene recuperato un nuovo lavoro da fare. Fin qui tutto bene, ma in questo momento abbiamo bisogno di una struttura di dati simile a una coda per contenere più lavori. Pensa a un caso in cui un utente tocca lo schermo in serie e un'attività impiega più tempo a finire. Quindi, abbiamo bisogno di una struttura di dati per contenere i lavori da svolgere in maniera first-in-first-out. Inoltre, si può immaginare che l'implementazione del thread ever-running-and-process-job-when-arrival tramite interrupt non sia facile e porta a un codice complesso e spesso non mantenibile. Preferiremmo creare un nuovo meccanismo per tale scopo, e questo è lo scopo di Looper . Il documento ufficiale della classe Looperdice "I thread per impostazione predefinita non hanno un loop di messaggi associato" e Looper è una classe "utilizzata per eseguire un loop di messaggi per un thread". Ora puoi capire cosa significa.
Per rendere le cose più chiare, controlliamo il codice in cui viene trasformato il thread principale. Succede tutto nella classe ActivityThread . Nel suo metodo main (), puoi trovare sotto il codice, che trasforma un normale thread principale in qualcosa di cui abbiamo bisogno.
public final class ActivityThread {
...
public static void main(String[] args) {
...
Looper.prepareMainLooper();
Looper.loop();
...
}
}
e Looper.loop()
metodo eseguono il ciclo all'infinito e accodano un messaggio ed elaborano uno alla volta:
public static void loop() {
...
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
msg.target.dispatchMessage(msg);
...
}
}
Quindi, sostanzialmente Looper è una classe creata per risolvere un problema che si verifica nel framework della GUI. Ma questo tipo di esigenze può verificarsi anche in altre situazioni. In realtà è un modello abbastanza famoso per l'applicazione multi-thread, e puoi saperne di più in " Programmazione concorrente in Java " di Doug Lea (In particolare, il capitolo 4.1.4 "Discussioni dei lavoratori" sarebbe utile). Inoltre, puoi immaginare che questo tipo di meccanismo non sia unico nel framework Android, ma tutto il framework GUI potrebbe aver bisogno di un po 'simile a questo. Puoi trovare quasi lo stesso meccanismo nel framework Java Swing.