消息处理管道


TODO: 待写

消息处理管道

一个App看作是系统,外部输入消息需要经过一系列处理,涉及不同接收者。消息处理的跟踪(Trace)和结果的保存。 比如设计一个用来接收服务器推送消息的处理框架?

以Android中处理InputEvent的设计作为借鉴。

案例

android.view.ViewRootImpl.deliverInputEvent()分发消息 InputStage处理阶段

使用了什么模式? 解决了哪些问题? 什么时候使用?

处理的阶段:InputStage

InputStage mFirstInputStage;

private void deliverInputEvent(QueuedInputEvent q) {        
        try {            

            InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
            if (stage != null) {
                stage.deliver(q);
            } else {
                finishInputEvent(q);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
}

/**
     * Base class for implementing a stage in the chain of responsibility
     * for processing input events.
     * <p>
     * Events are delivered to the stage by the {@link #deliver} method.  The stage
     * then has the choice of finishing the event or forwarding it to the next stage.
     * </p>
     */
    abstract class InputStage {
        private final InputStage mNext;

        protected static final int FORWARD = 0;
        protected static final int FINISH_HANDLED = 1;
        protected static final int FINISH_NOT_HANDLED = 2;

        /**
         * Creates an input stage.
         * @param next The next stage to which events should be forwarded.
         */
        public InputStage(InputStage next) {
            mNext = next;
        }

        /**
         * Delivers an event to be processed.
         */
        public final void deliver(QueuedInputEvent q) {
            if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
                forward(q);
            } else if (shouldDropInputEvent(q)) {
                finish(q, false);
            } else {
                apply(q, onProcess(q));
            }
        }

        /**
         * Marks the the input event as finished then forwards it to the next stage.
         */
        protected void finish(QueuedInputEvent q, boolean handled) {
            q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
            if (handled) {
                q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
            }
            forward(q);
        }

        /**
         * Forwards the event to the next stage.
         */
        protected void forward(QueuedInputEvent q) {
            onDeliverToNext(q);
        }

        /**
         * Applies a result code from {@link #onProcess} to the specified event.
         */
        protected void apply(QueuedInputEvent q, int result) {
            if (result == FORWARD) {
                forward(q);
            } else if (result == FINISH_HANDLED) {
                finish(q, true);
            } else if (result == FINISH_NOT_HANDLED) {
                finish(q, false);
            } else {
                throw new IllegalArgumentException("Invalid result: " + result);
            }
        }

        /**
         * Called when an event is ready to be processed.
         * @return A result code indicating how the event was handled.
         */
        protected int onProcess(QueuedInputEvent q) {
            return FORWARD;
        }

        /**
         * Called when an event is being delivered to the next stage.
         */
        protected void onDeliverToNext(QueuedInputEvent q) {
            if (mNext != null) {
                mNext.deliver(q);
            } else {
                finishInputEvent(q);
            }
        }

        protected boolean shouldDropInputEvent(QueuedInputEvent q) {
            if (mView == null || !mAdded) {
                Slog.w(TAG, "Dropping event due to root view being removed: " + q.mEvent);
                return true;
            } else if (!mAttachInfo.mHasWindowFocus &&
                  !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) &&
                  !isTerminalInputEvent(q.mEvent)) {
                // If this is a focused event and the window doesn't currently have input focus,
                // then drop this event.  This could be an event that came back from the previous
                // stage but the window has lost focus in the meantime.
                Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
                return true;
            }
            return false;
        }
    ...
    }
优质内容筛选与推荐>>
1、胭脂扣
2、微信公众平台开发教程(六)获取个性二维码
3、DataBinder.Eval(Container.DataItem,"username")
4、py 二级习题(加密与解密)
5、FlappyBirdWeb素材资源


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号