状态机一般都会重写父类的三种方法enter(),processMessage(Messagemsg),exit(),
1. 其中enter()方法是每次进入都会执行类似构造函数,
2. exit()类似析构函数,
3. 而processMessage()用来处理不同的请求。
示例:
finalclass AttachingState extends State {
@Override
publicvoid enter() {
Log.d(LOG_TAG, getName() + " enter msgId : " + mId);
}
@Override
publicbooleanprocessMessage(Message msg) {
boolean retVal = HANDLED;
switch (msg.what) {
caseEVENT_ATTACH_FILE_DONE:
AsyncResultar = (AsyncResult) msg.obj;
FtResult result = (FtResult) ar.result;
return retVal;
}
}
启动状态机的步骤:
1. 首先需要通过addState添加上面准备好的State实例,每一个State都可以添加一个自身的State和一个parentState。
2. 添加完所有的状态后就调用setInitialState设置一个初始状态。
3. 当经过1,2步骤后就要调用StateMachine:start()函数启动状态机机。
4. 当我们通过StateMachine:sendMessage发送消息的时候,StateMachine就会找到当前的State调用其processMessage来做相应的处理动作,
如果当前状态在处理完相应的事务后需要切换到新的状态就需要调用transitionTo(IStatedestState)设置mDestState的值。
示例:
@Override
protectedvoid initState(StatecurrentState) {
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mAttachingState, mDefaultState);
addState(mAttachedState, mDefaultState);
addState(mSendingState, mDefaultState);
addState(mAcceptingState, mDefaultState);
addState(mInProgressState, mDefaultState);
addState(mCompletedState, mDefaultState);
addState(mCancelingState, mDefaultState);
addState(mCanceledState, mDefaultState);
addState(mRetryState, mDefaultState);
Log.d(LOG_TAG, "setting current state as " + currentState.getName()
+ "for messageId : " + mId);
setInitialState(currentState);
start();
}
注意:
1. 上面说过一个State可能包含一个Parent State,如果在当前的State中没有能处理发送来的msg的时候,就要向上找其父State来处理,依次向上遍历,
如果所有的State都不能处理的话就会调用SmHandler:unhandledMessage来处理。
2. 另外两个方法:deferMessage和sendMessageAtFrontOfQueue,在代码中可以通过deferMessage向mDeferredMessages这种存放暂时不处理的消息。
在每此处理完新旧状态更新的时候就要调用sendMessageAtFrontOfQueue将mDeferredMessages中的消息优先发送出去(有可能是在A状态deferMessage的消息,切换到B状态后才发送出去,此时就应该B状态去处理这个消息),
每次发送完就会清空mDeferredMessages一次。
例如RCS项目中FT在FtMsrpMessage类中使用状态转换机制:
InitialState-->AttachingState-->AttachedState-->SendingState-->InProgressState-->CompletedState(另外CancelingState-->CanceledState可以在前面的执行过程中调用来取消文件传输)
图表解释:
mP0
/ \
mP1 mS0
/ \
mS2 mS1
/ \ \
mS3 mS4 mS5 ---> initial state
如上图,添加了mS5至mP0的8个状态,其中mS1是mS5的父状态,mP1是mS1的父状态,依次类推。上图可以看出mS5是初始状态,当启用状态机时调用StateMachine:start()会依次调用mP0--mP1--mS1--mS5的enter函数,并将他们每一个对应的StateInfo的active置为true。最后调用的是mS5,所以当前的状态进入mS5。此时如果外面有消息通过StateMachine:sendMessage发送进来,就会调用当前状态机的processMessage的方法来处理,如果当前状态处理不成功就调用父类处理消息直到处理成功(如果mS5就处理成功就跳出了,就不会进入mS1,以此类推)。
假设现在mS5处理发送来的消息成功,并且transitionTo(mS4),往上遍历发现有共同祖先mP1,那么就会依次调用mS5---mS1的exit函数,依次调用mS2---mS4的enter函数从而进入mS4状态。现在处于active的状态就是mS4,mS2,mP1,mP0了,下次来消息的时候就该mS4来处理了。