Android中的处理程序类是如何工作的

29

我是一个新手,正在阅读官方Android网站上的演示应用程序。我遇到了一个名为Handler类的方法,叫做postDelayed(Runnable r, long milliseconds)

请问有人能解释一下这个方法是干什么用的吗?


http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20long) - J. Steen
很好,它是自我解释的。在翻译器中检查这些单词:post、delayed、runnable... 或者只需在文档中检查方法引用即可。 - Selvin
2
你应该阅读文档。 - Blackbelt
我已经阅读了文档,但并没有完全理解它的含义。 - Rajat
3个回答

52

您可以查看文档

但是要理解文档,您应该首先了解几个概念:消息、消息队列、处理程序和循环器以及它们之间的关系

以下说明了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是线程本地对象,每个线程都有一个Looper。每个Looper关联着一个消息队列。Looper不断从队列中获取消息(可以称为"任务"、"命令"或其他你想要称呼的东西),然后将消息分发给它的目标Handler,来处理该消息(例如通过调用包含在消息中的Runnable进行回调)。当队列中没有消息时,线程会阻塞直到有新的消息到达。要停止一个Looper,必须在其上调用quit()方法(这可能不会立即停止循环,而是设置一个私有标志,该标志会周期性地从循环中检查,以通知它停止)。

Android框架提供了Handler类来简化操作。当你创建一个Handler实例时,它(默认情况下)已绑定到当前线程已附加的Looper。(Handler知道要连接到哪个Looper,因为我们之前调用了prepare()方法,该方法将Looper的引用存储在ThreadLocal中。)

有了Handler,你只需调用post()方法就可以"将一个消息放入线程的消息队列中"(这样说吧)。Handler会处理所有的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服务中,Handler被广泛使用。 Android支持应用程序间通信。通常情况下,当我们实现一个不需要处理多线程的服务时,我们实现一个Handler,它接收来自客户端的每个调用的回调。然后创建一个Messenger对象(指向Handler的引用),它是一个Binder对象并在客户端绑定此服务时返回此对象。因此,客户端可以使用这个Messenger向这个服务发送消息(进入线程本地队列,通过Looper发送到Handler)并让Handler进行处理。代码示例如下:

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

6

postDelayed (Runnable r, long delayMillis)

这个方法会将 Runnable r 添加到消息队列中,在指定的时间后运行。该 runnable 将在此处理程序所附加的线程上运行。

  • Runnable 表示可执行的命令。

  • delayMillis 表示应在延迟执行之后的时间。

基本上,它推迟了命令(可能是一些代码)的执行,以便在指定的时间后执行该命令(delayMillis)。


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

欢迎来到Stack Overflow!虽然这段代码可能回答了问题,但提供有关它如何以及/或为什么解决问题的附加上下文将改善答案的长期价值。请记住,您正在为未来的读者回答问题,而不仅仅是现在提问的人!请编辑您的答案以添加解释,并指出适用的限制和假设。此外,提到为什么这个答案比其他答案更合适也没有坏处。 - ItamarG3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接