Ответ 1
Вы можете увидеть документацию.
Но чтобы понять документы, вы должны сначала понять несколько концепций: Message, Message Queue, Handler and Looper и их relationship.
Ниже показано, как работает Looper, он показывает, что looper - это локальный объект потока и его связь с 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();
}
}
}
}
Несколько замечаний:
Looper - это локальный объект потока, так что каждый поток имеет один петлитель. Каждый петлитель связан с очередью сообщений. Петлеер постоянно получает сообщения ( "задачи", "команды" или все, что вы хотите называть их) из очереди, и отправляете сообщение своей цели, которая является обработчиком для обработки этого сообщения (например, путем вызова Runnable, содержащегося в сообщение). Когда в очереди нет сообщений, поток блокируется до появления новых сообщений. Чтобы остановить Looper, вам нужно вызвать quit() на нем (что, вероятно, не сразу останавливает цикл, а скорее устанавливает закрытый флаг, который периодически проверяется из цикла, сигнализируя о его остановке).
Android framework предоставляет класс Handler для упрощения. Когда вы создаете экземпляр Handler, он (по умолчанию) привязан к Looper, уже прикрепленному к текущему потоку. (Обработчик знает, к чему привязать Looper, потому что мы раньше вызывали prepare(), который хранил ссылку на Looper в ThreadLocal.)
С помощью Handler вы можете просто вызвать post(), чтобы "поместить сообщение в очередь сообщений потока" (так сказать). Обработчик позаботится обо всех материалах обратного вызова IdleHandler и убедится, что вы выполнили свой Runnable. (Он также может проверить правильность времени, если вы отправили с задержкой.)
В следующем коде показаны типичные способы их использования.
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();
}
}
Обработчик широко используется в службах Android. Поддержка Android inter application. Обычно, когда мы реализуем сервис, который не нуждается в обработке многопоточности, мы реализуем обработчик, который получает обратный вызов для каждого вызова от клиента. Затем создайте объект Messenger (ссылка на обработчик), который является объектом Binder и возвращает этот объект клиентам, когда они связывают эту службу. Таким образом, клиент может использовать этот Messenger для отправки сообщений (в локальную очередь потока, отправки обработчику через Looper) этой службе и получать их в обработчике. Образец кода прилагается:
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();
}
}