处理程序类如何在Android中运行

Raj*_*jat 28 android handler

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

任何人都可以解释这种方法的作用吗?

Sta*_*kER 51

你可以看到文档.

但要理解文档,首先应该理解几个概念:Message,Message Queue,Handler和Looper,以及它们之间的关系.

下面说明了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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

几点评论:

Looper是一个线程本地对象,每个线程都有一个looper.每个循环器都与一个消息队列相关联.looper不断地从队列中获取消息("任务","命令"或任何你喜欢称之为的命令),并将消息发送到其目标,该目标是处理该消息的处理程序(例如,通过回调包含在其中的Runnable)消息).当队列中没有剩余消息时,线程会阻塞,直到有新消息.要停止Looper,你必须在它上面调用quit()(这可能不会立即停止循环,而是设置一个私有标志,从循环中定期检查,表示它停止).

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

使用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();
  }
Run Code Online (Sandbox Code Playgroud)

}

Handler广泛用于Android服务.Android支持跨应用程序通信.通常,当我们实现一个不需要处理多线程的服务时,我们实现了一个Handler,它接收来自客户端的每个调用的回调.然后创建一个Messenger对象(对Handler的引用),它是一个Binder对象,并在绑定此服务时将此对象返回给客户端.因此,客户端可以使用此Messenger将消息(进入线程本地队列,通过Looper发送给处理程序)发送到此服务,并在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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Sah*_* Mj 6

postDelayed (Runnable r, long delayMillis)

导致Runnable r要添加到消息队列,在指定的时间量过去后运行.在runnable将要为该处理器所连接的线程上运行.

  • Runnable表示可以执行的命令.

  • delayMillis表示应该执行的时间.

基本上,它延迟了特定时间段(delayMillis)的命令执行(某些代码可能),以便在指定时间后执行命令.