Je suis nouveau sur Android et je lisais les applications de démonstration sur le site officiel Android. Et je suis tombé sur une méthode de classe Handler
nommée comme postDelayed(Runnable r, long milliseconds)
.
Quelqu'un peut-il expliquer ce que fait cette méthode?
Vous pouvez voir le documentation .
Mais pour comprendre les documents, vous devez d'abord comprendre plusieurs concepts: Message, Message Queue, Handler et Looper , et leur relation .
Ce qui suit illustre le fonctionnement du Looper, il montre que le looper est un objet local de thread et sa relation avec MessageQueue:
class Looper{
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
msg.recycle();
}
}
}
}
Plusieurs remarques:
Looper est un objet local de thread tel que chaque thread a un looper. Chaque looper est associé à une file d'attente de messages. Le looper récupère continuellement des messages ("tâches", "commandes" ou tout ce que vous voulez les appeler) de la file d'attente et envoie le message à sa cible, qui est un gestionnaire pour gérer ce message (par exemple en rappelant un Runnable contenu dans le message). Lorsqu'il ne reste aucun message dans la file d'attente, le thread se bloque jusqu'à ce qu'il y ait de nouveaux messages. Pour arrêter un Looper, vous devez appeler quit () dessus (ce qui n'arrête probablement pas la boucle immédiatement, mais définit plutôt un indicateur privé qui est vérifié périodiquement à partir de la boucle, lui signalant de s'arrêter).
Le framework Android fournit la classe Handler pour simplifier les choses. Lorsque vous créez une instance de gestionnaire, elle est (par défaut) liée au Looper déjà attaché au thread actuel. (Le gestionnaire sait à quel Looper s'attacher car nous avons appelé prepare () plus tôt, qui stockait une référence au Looper dans un ThreadLocal.)
Avec un gestionnaire, vous pouvez simplement appeler post () pour "mettre un message dans la file d'attente de messages du thread" (pour ainsi dire). Le gestionnaire s'occupera de toutes les tâches de rappel IdleHandler et s'assurera que votre Runnable publié est exécuté. (Il pourrait également vérifier si le moment est déjà venu, si vous avez posté avec un retard.)
Le code suivant montre les façons typiques dont nous les utilisons.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
Le gestionnaire est largement utilisé dans Android services. Android prend en charge la communication inter-applications. Typiquement, lorsque nous implémentons un service, qui n'a pas besoin de gérer le multithreading, nous implémentons un gestionnaire qui reçoit un rappel pour chaque appel d'un client. Créez ensuite un objet Messenger (référence au gestionnaire), qui est un objet Binder et renvoyez cet objet aux clients lorsqu'ils lient ce service. Le client peut donc utiliser ce Messenger pour envoyer des messages (dans la file d'attente locale du thread, envoyer au gestionnaire via Looper) à ce service et les faire gérer dans le gestionnaire. Un exemple de code est joint:
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
postDelayed (Runnable r, long delayMillis)
Provoque le Runnable r
à ajouter à la file d'attente des messages, à exécuter après la durée spécifiée. runnable
sera exécuté sur le thread auquel ce gestionnaire est attaché.
Runnable Représente une commande qui peut être exécutée.
delayMillis représente le temps après lequel il doit être exécuté.
Fondamentalement, cela retarde l'exécution de la commande (du code peut-être) pendant une période de temps particulière (delayMillis
), de manière à exécuter la commande après un temps spécifié.