Я новичок в android и читаю демо-приложения на официальном сайте Android. И я наткнулся на метод класса Handler
, названный как postDelayed(Runnable r, long milliseconds)
.
Может кто-нибудь объяснить, что делает этот метод?
Я новичок в android и читаю демо-приложения на официальном сайте Android. И я наткнулся на метод класса Handler
, названный как postDelayed(Runnable r, long milliseconds)
.
Может кто-нибудь объяснить, что делает этот метод?
Вы можете увидеть документацию.
Но чтобы понять документы, вы должны сначала понять несколько концепций: 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();
}
}
postDelayed (Runnable r, long delayMillis)
Вызывает добавление Runnable r
в очередь сообщений, которая должна запускаться по истечении заданного промежутка времени. runnable
будет выполняться в потоке, к которому прикреплен этот обработчик.
Runnable Представляет команду, которая может быть выполнена.
delayMillis представляет время, после которого оно должно быть выполнено.
В принципе, он задерживает выполнение команды (может быть, некоторый код) в течение определенного периода времени (delayMillis
), чтобы выполнить команду после указанного времени.
public class ApiHandler {
public static final String BASE_URL = "http://xxx.yyy/xx/";
private static final long HTTP_TIMEOUT = TimeUnit.SECONDS.toMillis(120);
private static Webservices apiService;
public static Webservices getApiService() {
if (apiService == null) {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS);
okHttpClient.setWriteTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS);
okHttpClient.setReadTimeout(HTTP_TIMEOUT, TimeUnit.MILLISECONDS);
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(BASE_URL)
.setClient(new OkClient(okHttpClient))
.setConverter(new GsonConverter(new Gson()))
.build();
apiService = restAdapter.create(Webservices.class);
/*RestAdapter.Builder builder = new RestAdapter.Builder();
builder.setConverter(new StringConverter())
.setEndpoint(BASE_URL)
.setClient(new OkClient(new OkHttpClient()))
.setLogLevel(RestAdapter.LogLevel.NONE);
RestAdapter adapter = builder.build();
apiService = adapter.create(Webservices.class);*/
return apiService;
} else {
return apiService;
}
}
}