Android StateMachine使用

1. StateMachineJar的封装

把源码的如下3个文件,提取为jar包使用就可以
frameworks/base/core/java/com/android/internal/util/StateMachine.java
frameworks/base/core/java/com/android/internal/util/State.java
frameworks/base/core/java/com/android/internal/util/IState.java

2. 使用示例

StateMachine的基本使用必须按如下四个步骤进行,缺一不可:

  • 继承StateMachine,StateMachine类的构造函数是Protect访问权限,所以只能通过继承实现实例化
  • 通过addState方法构造状态层次结构(树形结构,可多棵),状态层次结构根据状态转移图构建,各种状态需要继承State类,实现自己相应业务逻辑
  • 通过setInitialState设置初始状态
  • 调用start方法启动状态机
    其他常用API如下表所示:
MethodDescription
quit()停止状态机,会进入QuttingState
sendMessage(Message msg)发送一个消息,供各状态处理
deferMessage(Message msg)发送一个延迟消息,在下一次状态转换时,才会被放入消息队列
transitionTo(IState state)转移至相应状态
transitionToHaltingState()进入HaltingState

示例:

继承StateMachine并初始化

package com.mtest.statemachine;


import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.bluesky.statemachinejar.State;
import com.bluesky.statemachinejar.StateMachine;
import com.mtest.statemachine.state.ErrorState;
import com.mtest.statemachine.state.ExitState;
import com.mtest.statemachine.state.IdleState;
import com.mtest.statemachine.state.NormalState;
import com.mtest.statemachine.state.StartRecgState;

import java.util.HashMap;
import java.util.Map;

public class FaceStateMachine  extends StateMachine {

    private static final String NAME = "FaceStateMachine";
    private static final String TAG = "FaceStateMachine";

    /*定义的几个状态机状态,包括初始状态,开始识别,识别正常,识别异常,退出识别*/
    public static final int IDLE_STATE = 1;
    public static final int START_RECG_STATE = 2;
    public static final int RECG_NORMAL_STATE = 3;
    public static final int RECG_ERROR_STATE = 4;
    public static final int RECG_EXIT_STATE = 5;


    private static volatile FaceStateMachine sFaceStateMachine;

    private Map<String, State> mStateMap = new HashMap<>();

    /*继承的StateMachine,super需要添加状态机名字,并且运行在主线程*/
    protected FaceStateMachine() {
        super(NAME, Looper.getMainLooper());

        initStateMachine();
    }


    /*状态机这里采用单例模式,用于管理*/
    public static FaceStateMachine get() {
        synchronized (FaceStateMachine.class) {
            if (sFaceStateMachine == null) {
                synchronized (FaceStateMachine.class) {
                    sFaceStateMachine = new FaceStateMachine();
                }
            }
        }
        return sFaceStateMachine;
    }


    /*
    * 构造状态机需要添加初始状态,StateMachine是树结构的状态机,因此要添加父节点
    * setInitialState:设置初始状态 start开始状态机
    * */
    private void initStateMachine() {
        IdleState idleState = new IdleState();
        StartRecgState startRecg = new StartRecgState();

        addInitStateMachine(idleState);
        addInitStateMachine(startRecg);
            addInitStateMachine(new NormalState(), startRecg);
            addInitStateMachine(new ExitState(), startRecg);
            addInitStateMachine(new ErrorState(), startRecg);

        setInitialState(idleState);

        start();

    }


    /*
    * 调用addState完成添加状态机,可以直接添加,也可以添加父类关系
    *
    * mStateMap用于保存,状态State的集合,通过getState()获取状态名,用于切状态
    * */
    private void addInitStateMachine(State childState) {
        mStateMap.put(childState.getClass().getSimpleName(),childState);
        addState(childState);
    }

    private void addInitStateMachine(State childState, State parentState) {
        mStateMap.put(childState.getClass().getSimpleName(),childState);
        addState(childState, parentState);
    }

    public State getState(String name) {
        return mStateMap.get(name);
    }


    /*
    * 如果不添加sendMessage,直接调用transitionTo,根本就不会执行切状态
    *
    * */
    /*模拟发送消息*/
    public void doSendEventByStartRecg() {
        Log.d(TAG , "doSendEventByStartRecg:");
        transitionTo(getState(StartRecgState.class.getSimpleName()));
        sendMessage(START_RECG_STATE);
    }



}

base状态机

package com.mtest.statemachine.state;

import android.os.Message;
import android.util.Log;

import com.bluesky.statemachinejar.State;
import com.bluesky.statemachinejar.StateMachine;
import com.mtest.statemachine.FaceStateMachine;


/*用于自己创建的状态机基类,作为所有state继承用*/
public class BaseState extends State {

    public static final String TAG = BaseState.class.getSimpleName();


    /*
    * 状态机进程时候执行,像初始化
    * */
    @Override
    public void enter() {
        super.enter();

        Log.d(TAG,"enter...");
    }

    /*退出时候执行,释放资源*/
    @Override
    public void exit() {
        super.exit();

        Log.d(TAG,"exit...");
    }

    /*
    *消息处理,发送消息后才能切换状态机,不知道为什么
    * */
    @Override
    public boolean processMessage(Message msg) {

        switch (msg.what) {
            case FaceStateMachine.START_RECG_STATE:
                Log.d(TAG, "processMessage: START_RECG_STATE");
                break;
            case FaceStateMachine.RECG_NORMAL_STATE:
                Log.d(TAG, "processMessage: RECG_NORMAL_STATE");
                break;
            case FaceStateMachine.RECG_ERROR_STATE:
                Log.d(TAG, "processMessage: RECG_ERROR_STATE");
                break;
            case FaceStateMachine.RECG_EXIT_STATE:
                Log.d(TAG, "processMessage: RECG_EXIT_STATE");
                break;
            default:
                break;
        }


        return StateMachine.NOT_HANDLED;
    }

    @Override
    public String getName() {
        return super.getName();
    }
}

定义一个状态

package com.mtest.statemachine.state;

import android.os.Message;
import android.util.Log;

import com.mtest.presenter.StateMessageHander;
import com.mtest.statemachine.FaceStateMachine;

public class ExitState extends BaseState{

    public static final String TAG = ExitState.class.getSimpleName();

    @Override
    public void enter() {
        super.enter();
        Log.d(TAG, "ExitState: enter");
        StateMessageHander.getInstance().sendEmptyMessage(StateMessageHander.DO_RECG_EXIT_STATE);
    }

    @Override
    public void exit() {
        super.exit();
    }

    @Override
    public boolean processMessage(Message msg) {

        switch (msg.what) {
            case FaceStateMachine.START_RECG_STATE:
                Log.d(TAG, "processMessage: START_RECG_STATE");
                //FaceStateMachine.get().transitionTo(FaceStateMachine.get().getState());
                break;
            case FaceStateMachine.RECG_NORMAL_STATE:
                Log.d(TAG, "processMessage: RECG_NORMAL_STATE");
                break;
            case FaceStateMachine.RECG_ERROR_STATE:
                Log.d(TAG, "processMessage: RECG_ERROR_STATE");
                break;
            case FaceStateMachine.RECG_EXIT_STATE:
                Log.d(TAG, "processMessage: RECG_EXIT_STATE");
                break;
            default:
                break;
        }

        return super.processMessage(msg);
    }
}

3. 使用注意

通常,我们会在 State.processMessage 内部,通过调用 transitionTo 函数执行一次状态转换,而调用这个函数只是将你要转换的状态存入一个临时的对象中:

protected final void transitionTo(IState destState) {
        mSmHandler.transitionTo(destState);
}
private final void transitionTo(IState destState) {
            mDestState = (State) destState;
}
复制代码真正的状态转换将发生在 SmHandler.handleMessage 函数执行之后:
 public final void handleMessage(Message msg) {
            if (!mHasQuit) {
                ...
                performTransitions(msgProcessedState, msg);//变更状态
            }
        }


参考链接

[Android] 状态机 StateMachine 源码剖析

Android StateMachine

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值