Подтвердить что ты не робот

Как работают классы обработчиков в Android

Я новичок в android и читаю демо-приложения на официальном сайте Android. И я наткнулся на метод класса Handler, названный как postDelayed(Runnable r, long milliseconds).

Может кто-нибудь объяснить, что делает этот метод?

4b9b3361

Ответ 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();
    }
}

Ответ 2

postDelayed (Runnable r, long delayMillis)

Вызывает добавление Runnable r в очередь сообщений, которая должна запускаться по истечении заданного промежутка времени. runnable будет выполняться в потоке, к которому прикреплен этот обработчик.

  • Runnable Представляет команду, которая может быть выполнена.

  • delayMillis представляет время, после которого оно должно быть выполнено.

В принципе, он задерживает выполнение команды (может быть, некоторый код) в течение определенного периода времени (delayMillis), чтобы выполнить команду после указанного времени.

Ответ 3

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;
    }
  }
}