看看实际代码中的责任链模式
Android 5.1源码中的ViewRootImpl.java中就使用了责任链模式。
这是一张责任链的图(来自百度百科):
/**
* Base class for implementing a stage in the chain of responsibility
* for processing input events.
* 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.
*/
abstract class InputStage
InputStage作为责任链模式中的抽象处理者(Handler)角色
定义出一个处理请求的接口。
如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。
这个角色通常由一个Java抽象类或者Java接口实现。
上图中Handler类的聚合关系给出了具体子类对下家的引用
它有一个后继者:private final InputStage mNext;
/** * 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)); } }
如果QueuedInputEvent已经被处理过,那么就会有FLAG_FINISHED这个flag,那么就应该沿着责任链继续传递下去;如果尚未被处理,那么就调用onProcess方法去处理。
/** * Forwards the event to the next stage. */ protected void forward(QueuedInputEvent q) { onDeliverToNext(q); } /** * 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); } }
而每一个具体的,都应该实现onProcess这个方法,去做自己需要做的处理。
onProcess方法可能返回三种结果:FORWARD,FINISH_HANDLED和FINISH_NOT_HANDLED
除了第一种表明你并不想处理,或是你虽然处理了,但还是希望后继者能继续处理,其它两种都表明你已经把这件事搞定了,你的后继者不应该再多管闲事啦。
下面看看client是如何使用的
在setView方法中
InputStage mFirstInputStage;
InputStage mFirstPostImeInputStage;
InputStage mSyntheticInputStage;
// Set up the input pipeline. CharSequence counterSuffix = attrs.getTitle(); mSyntheticInputStage = new SyntheticInputStage(); InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage); InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage, "aq:native-post-ime:" + counterSuffix); InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage); InputStage imeStage = new ImeInputStage(earlyPostImeStage, "aq:ime:" + counterSuffix); InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage); InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage, "aq:native-pre-ime:" + counterSuffix); mFirstInputStage = nativePreImeStage; mFirstPostImeInputStage = earlyPostImeStage;
private void deliverInputEvent(QueuedInputEvent q) { if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0); } InputStage stage; if (q.shouldSendToSynthesizer()) { stage = mSyntheticInputStage; } else { stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage; } if (stage != null) { stage.deliver(q); } else { finishInputEvent(q); } }