Android中的状态机(续)
上周有点累,这次终于把未完成的代码给写完了,并调试完毕。
代码仍有待改进的地方:
1. 内部类的使用,提高代码的隐藏性以及类之间的密切关联程度(外围类与内部类之间的互访问)。
2. 其它的,希望大家多多提出建议。 联系 QQ 402320131
上次承诺要谈谈android开机建立PDP时状态机的变化:
大致是 DcInactiveState -> DcActivatingState -> DcActiveState
状态机在建立PDP的过程只是一个很小的部分,在其上层需要framework维护好下发和取消PDP的时机,在其下层需要modem提供NAS服务。所以PDP还是很复杂的,后续介绍下modem侧的数据业务,现在还在着手学习中。
提供代码:
package com.zte.liu.statemachine;
import com.zte.liu.messagehandler.HandlerThread;
import com.zte.liu.messagehandler.Looper;
import com.zte.liu.messagehandler.Message;
public class HierarchicalStateMachine {
private HsmHandler mHandler;
private HandlerThread mHandlerThread;
private DefaultState defaultState = new DefaultState();
private InactiveState inActiveState = new InactiveState();
private ActivingState activingState = new ActivingState();
private ActiveState activeState = new ActiveState();
private HaltingState haltingState = new HaltingState();
private QuitingState quitingState = new QuitingState();
private static final boolean HANDLED = true;
private static final boolean UNHANDLED = false;
public static final int CMD_1 = 1;
public static final int CMD_2 = 2;
public static final int CMD_3 = 3;
public static final int CMD_4 = 4;
public static final int CMD_5 = 5;
public static final int CMD_6 = 6;
public HierarchicalStateMachine(){
mHandlerThread = new HandlerThread();
mHandlerThread.start();
Looper looper = mHandlerThread.getLooper();
mHandler = new HsmHandler(looper);
}
public void init(){
addState(defaultState);
addState(inActiveState, defaultState);
addState(activingState, defaultState);
addState(activeState, defaultState);
addState(haltingState);
addState(quitingState);
setInitialState(inActiveState);
}
private class DefaultState extends HierarchicalState{
@Override
public void enter() {
System.out.println("defaultState.enter()");
}
@Override
public void exit() {
System.out.println("defaultState.exit()");
}
@Override
public boolean processMessage(Message msg) {
boolean retVal = UNHANDLED;
switch(msg.what){
}
return retVal;
}
}
private class InactiveState extends HierarchicalState{
@Override
public void enter() {
System.out.println("inActiveState.enter()");
}
@Override
public void exit() {
System.out.println("inActiveState.exit()");
}
@Override
public boolean processMessage(Message msg) {
System.out.println("inActiveState.processMessage what=" + msgToStr(msg.what));
boolean retVal = UNHANDLED;
switch(msg.what){
case CMD_1:
sendMessage(obtainMessage(CMD_2, null));
transitionTo(activingState);
retVal = HANDLED;
break;
default:
retVal = UNHANDLED;
}
return retVal;
}
}
private class ActivingState extends HierarchicalState{
@Override
public void enter() {
System.out.println("activingState.enter()");
}
@Override
public void exit() {
System.out.println("activingState.exit()");
}
@Override
public boolean processMessage(Message msg) {
System.out.println("activingState.processMessage what=" + msgToStr(msg.what));
boolean retVal = UNHANDLED;
switch(msg.what){
case CMD_2:
sendMessage(obtainMessage(CMD_3, null));
deferMessage(msg);
transitionTo(activeState);
retVal = HANDLED;
break;
default:
retVal = UNHANDLED;
}
return retVal;
}
}
private class ActiveState extends HierarchicalState{
@Override
public void enter() {
System.out.println("activeState.enter()");
}
@Override
public void exit() {
System.out.println("activeState.exit()");
}
@Override
public boolean processMessage(Message msg) {
System.out.println("activeState.processMessage what=" + msgToStr(msg.what));
boolean retVal = UNHANDLED;
switch(msg.what){
case CMD_2:
retVal = HANDLED;
break;
case CMD_3:
sendMessage(obtainMessage(HsmHandler.HALTING_MESSAGE, null));
transitionTo(haltingState);
retVal = HANDLED;
break;
default:
retVal = UNHANDLED;
}
return retVal;
}
}
private class HaltingState extends HierarchicalState{
@Override
public void enter() {
System.out.println("haltingState.enter()");
halt();
}
@Override
public boolean processMessage(Message msg) {
System.out.println("activeState.processMessage what=HALTING_MESSAGE");
sendMessage(obtainMessage(HsmHandler.QUITING_MESSAGE, null));
transitionTo(quitingState);
return HANDLED;
}
}
private class QuitingState extends HierarchicalState{
@Override
public void enter() {
System.out.println("activeState.exit()");
}
@Override
public void exit() {
System.out.println("activeState.exit()");
}
@Override
public boolean processMessage(Message msg) {
return super.processMessage(msg);
}
}
public void addState(HierarchicalState state){
mHandler.addState(state, null);
}
public void addState(HierarchicalState state, HierarchicalState parent){
mHandler.addState(state, parent);
}
public void setInitialState(HierarchicalState state){
mHandler.setInitialState(state);
}
public void start(){
mHandler.completeConstruction();
mHandler.passState(haltingState, quitingState); //糟糕的做法
}
public Message obtainMessage(int what, Object obj){
return mHandler.obtainMessage(what, obj);
}
public void sendMessage(Message msg){
if(msg != null){
msg.sendToTarget();
}
}
public void deferMessage(Message msg){
mHandler.deferMessage(msg);
}
public void transitionTo(HierarchicalState destState){
mHandler.transitionTo(destState);
}
private String msgToStr(int what){
String retVal = "";
switch(what){
case HsmHandler.QUITING_MESSAGE:
retVal = "QUITING_MESSAGE";
break;
case HsmHandler.HALTING_MESSAGE:
retVal = "HALTING_MESSAGE";
break;
case CMD_1:
retVal = "CMD_1";
break;
case CMD_2:
retVal = "CMD_2";
break;
case CMD_3:
retVal = "CMD_3";
break;
case CMD_4:
retVal = "CMD_4";
break;
case CMD_5:
retVal = "CMD_5";
break;
case CMD_6:
retVal = "CMD_6";
break;
default:
retVal = "UNKNOW MESSAGE";
break;
}
return retVal;
}
private void halt(){
synchronized(this){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.zte.liu.statemachine;
import java.util.ArrayList;
import java.util.HashMap;
import com.zte.liu.messagehandler.Handler;
import com.zte.liu.messagehandler.Looper;
import com.zte.liu.messagehandler.Message;
import com.zte.liu.messagehandler.MessageQueue;
public class HsmHandler extends Handler {
private HashMap<HierarchicalState, StateInfo> mStateInfo = new HashMap<HierarchicalState, StateInfo>();
private HierarchicalState mInitialState = null;
private HierarchicalState mDestState = null;
private ArrayList<StateInfo> mInitialStateList = new ArrayList<StateInfo>();
private ArrayList<Message> mDeferredMessages = new ArrayList<Message>();
//一种糟糕的做法,将HierarchicalStateMaching中的两个状态机传入到这里。一种好的做法是将本类作为
//HierarchicalStateMaching的内部类。
private HierarchicalState haltingState = null;
private HierarchicalState quitingState = null;
public static final int QUITING_MESSAGE = 100;
public static final int HALTING_MESSAGE = 101;
public HsmHandler(Looper looper) {
super(looper);
}
private class StateInfo{
HierarchicalState state;
HierarchicalState parentState;
boolean active;
}
public void addState(HierarchicalState state, HierarchicalState parentState){//只在非多线程情况
if(state == null){
throw new RuntimeException("state cannot be null when adding state.");
}
/* if(mStateInfo.containsKey(state) && mStateInfo.get(state).parentState!=parentState){
throw new RuntimeException("we cannot add a state with different parents.");
}
*/
if(mStateInfo.containsKey(state)){
return;
}
StateInfo stateInfo = new StateInfo();
stateInfo.state = state;
stateInfo.parentState = parentState;
stateInfo.active = false;
mStateInfo.put(state, stateInfo);
}
public void setInitialState(HierarchicalState state){
if(!mStateInfo.containsKey(state)){
throw new RuntimeException("cannot set a initial state which is not contained in the build tree.");
}
mInitialState = state;
}
public void completeConstruction(){
if(mInitialState == null){
return;
}
StateInfo initialStateInfo = mStateInfo.get(mInitialState);
while(initialStateInfo != null){
mInitialStateList.add(initialStateInfo);
if(initialStateInfo.parentState == null){
initialStateInfo = null;
}else{
initialStateInfo = mStateInfo.get(initialStateInfo.parentState);
}
}
invokeEnterMethods(null);
performTransitions();
}
public void passState(HierarchicalState haltingState, HierarchicalState quitingState){
this.haltingState = haltingState;
this.quitingState = quitingState;
}
public void invokeEnterMethods(StateInfo commonStateInfo){
int start = mInitialStateList.size() - 1;
for(int i=mInitialStateList.size()-1; i>=0; i--){
if(mInitialStateList.get(i) == commonStateInfo){
start = i - 1;
break;
}
}
for(int i=start; i>=0; i--){
StateInfo stateInfo = mInitialStateList.get(i);
stateInfo.state.enter();
stateInfo.active = true;
}
}
public void invokeExitMethods(StateInfo commonStateInfo){
for(int i=0; i<mInitialStateList.size(); i++){
StateInfo stateInfo = (StateInfo)mInitialStateList.get(i);
if(stateInfo != commonStateInfo){
stateInfo.state.exit();
stateInfo.active = false;
}else{
break;
}
}
}
public void performTransitions(){
if(mDestState == null){
return;
}
ArrayList<StateInfo> tempList = new ArrayList<StateInfo>();
StateInfo commonStateInfo = getCommonStateInfo(mDestState, tempList);
invokeExitMethods(commonStateInfo);
refreshInitialStateList(commonStateInfo, tempList);
invokeEnterMethods(commonStateInfo);
moveDeferredMsgAtFrontQueue();
mInitialState = mDestState;
mDestState = null;
}
public void deferMessage(Message msg){
mDeferredMessages.add(msg);
}
public void handleMessage(Message msg){//重写!!
processMsg(msg);
performTransitions();
}
public void transitionTo(HierarchicalState destState){
mDestState = destState;
}
private StateInfo getCommonStateInfo(HierarchicalState destState, ArrayList<StateInfo> tempList){
StateInfo stateInfo = mStateInfo.get(destState);
while(stateInfo!=null && stateInfo.active==false){
tempList.add(stateInfo);
if(stateInfo.parentState == null){
stateInfo = null;
}else{
stateInfo = mStateInfo.get(stateInfo.parentState);
}
}
return stateInfo;
}
private void refreshInitialStateList(StateInfo commonStateInfo, ArrayList<StateInfo> tempList){
/* 典型的错误代码1!!执行mInitialStateList.remove(i)时,影响了mInitialStateList.size()的值。。
for(int i=0; i<mInitialStateList.size(); i++){
if(mInitialStateList.get(i) != commonStateInfo){
mInitialStateList.remove(i);
}else{
break;
}
}
*/
/* 典型的错误代码2!!会出现数组越界。。
int initialStateListSize = mInitialStateList.size();
for(int i=0; i<initialStateListSize; i++){
if(mInitialStateList.get(i) != commonStateInfo){
mInitialStateList.remove(i);
}else{
break;
}
}
*/
for(int i=0; i<mInitialStateList.size(); ){
if(mInitialStateList.get(0) != commonStateInfo){
mInitialStateList.remove(0);
}else{
break;
}
}
if(commonStateInfo == null)
for(int i=tempList.size()-1; i>=0; i--){
mInitialStateList.add(0, tempList.get(i));
}
}
private void moveDeferredMsgAtFrontQueue(){
MessageQueue msgQueue = this.getLooper().getQueue();
for(int i=mDeferredMessages.size()-1; i>=0; i--){
msgQueue.addToFront(mDeferredMessages.remove(i));
}
}
private void processMsg(Message msg){
HierarchicalState currentState = mInitialState;
while(!currentState.processMessage(msg)){
currentState = mStateInfo.get(currentState).parentState;
if(currentState == null){
unhandledMessage(msg);
if(isQuit(msg)){
quitingState.exit();
}
break;
}
}
}
private void unhandledMessage(Message msg){
System.out.println("the message " + msg.what + " is not handled.");
}
private boolean isQuit(Message msg){
return msg.what == QUITING_MESSAGE;
}
}
package com.zte.liu.statemachine;
public class MiddleUser {
public static void main(String arg[]){
HierarchicalStateMachine stateMachine = new HierarchicalStateMachine();
stateMachine.init();
stateMachine.start();
stateMachine.sendMessage(stateMachine.obtainMessage(HierarchicalStateMachine.CMD_1, null));
try {
System.out.println("the main thread begin busy for 5 seconds...");
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("5 seconds over...");
synchronized(stateMachine){
stateMachine.notifyAll();
}
}
}
最后更新:2017-04-02 06:52:02