Android StateMachine 学习

今天学习记录下对状态机的学习
一、状态机使用的步骤

  1. 可以将源码的frameworks/base/core/java/com/android/internal/util里面把StateMachine.java 、State.java 、IState.java复制到project目录中
  2. 自定义StateMachine类 (如 MyLife) 继承StateMachine
  3. 自定义状态State ( 如MyLife中不同状态-睡觉、吃饭、工作学习等状态) 继承State:重写enter、processMsg、exit
  4. addState加入父状态、子状态,setInitialState初始化状态
  5. start() 函数调用 启动状态机stateMachine
  6. 使用状态机,发送持有更新状态常量的Msg
  7. quit() 函数是关闭状态机

二、部分代码如下

//2. 自定义StateMachine类 MyLife ,该类继承 StateMachine
public class MyLife extends StateMachine {

    private String TAG = "MyLife";

    IdleState mIdle = new IdleState();
    SleepingState mSleeping = new SleepingState();
    EatingState mEating = new EatingState();
    WorkingState mWorking = new WorkingState();
    RestingState mResting = new RestingState();
    ReadingState mReading = new ReadingState();
    PoemingState mPoeming = new PoemingState();

    private CompositeSubscription allSubscription = null;
    private static MyLife myLife = null;

    protected MyLife(String name) {
        super(name);
        Log.e(TAG,"new MyLife");
        allSubscription = new CompositeSubscription();
        //4.添加不同的状态,构成树形结构
        addState(mIdle);
        addState(mEating, mIdle);  //可以看作 midle 为 mEating 的父状态,mEating 为 midle 的 子状态
        addState(mWorking,mEating);
        addState(mReading,mWorking);
        addState(mPoeming,mReading);
        addState(mSleeping, mIdle);
        addState(mResting, mIdle);
        //4.setInitialState 设置一个初始状态
        setInitialState(mIdle);
    }

    public static MyLife getInstance(){
        if(myLife == null){
            myLife = new MyLife("mylife");
        }
        return myLife;
    }

    public void setContext(Context context){
        this.context = context;
    }

//3.定义状态机的不同状态,如闲暇时间 IdleState 继承与 State
    class IdleState extends State {
        //enter相当于初始化函数,类似于C++的构造函数,父状态先调用
        @Override
        public void enter() {
            Log.e(TAG,"IdleState enter");
        }
       //当有消息时,当前状态的 该函数被调用
        @Override
        public boolean processMessage(Message message) {

            Log.e(TAG,"xtk IdleState .processMessage what = " + message.what);
            switch(message.what) {
                case MsgState.MSG_STATE_WORKING:
                    Log.e(TAG,"xtk IdleState MSG_STATE_WORKING");
                    //6.转换状态 transitionTo
                    transitionTo(mEating);
                    //6.sendMessage发送消息
                    sendMessage(MsgState.MSG_STATE_EATTING);
                    break;
            }
            //注意该出这两种返回值写法,会出现不同的处理过程
            //return true;
            return super.processMessage(message);
        }
        //类似于C++的析构函数,子状态(树形结构中相对于上一级状态节点作为父状态)先调用
        @Override
        public void exit() {
            Log.e(TAG,"xtk IdleState exit");
        }
    }
//3.定义状态机的不同状态,如睡觉状态 SleepingState 继承与 State
    class SleepingState extends State {
        ......
    }
//3.定义状态机的不同状态,如吃饭状态 EatingState 继承与 State
    class EatingState extends State {
        ......
    }

    class WorkingState extends State {
        ......
    }

     ......

    private synchronized void testData(String num){

        int value = Integer.valueOf(num);
        Random random = new Random(10);
        if(value  == 8 && (random.nextInt() % 2) == 0){
            Log.e(TAG,"testData MSG_STATE_GOTOWC");
            transitionTo(mResting);
            sendMessage(MsgState.MSG_STATE_GOTOWC);
        }

        if(value  == 15){

            Log.e(TAG,"testData MSG_STATE_SLEEPING");
            transitionTo(mSleeping);
            sendMessage(MsgState.MSG_STATE_SLEEPING);
        }

        if(value > 20){
            MsgState.RUN = false;
        }
    }

    public void startState(){
        sendMessage(MsgState.MSG_STATE_WORKING);
    }
}

三、启动状态机

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

   private Button btn = null;
   private MyLife myLife = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = (Button)findViewById(R.id.txtBtn);
        btn.setOnClickListener(this);

        myLife = MyLife.getInstance();
    }

    @Override
    public void onClick(View v) {
        Log.e("test","on Click!");
        myLife.setContext(this);
        myLife.start();
        myLife.startState();
    }
}

四、状态机学习的总结

这里写图片描述

假设如上图的树形结构状态,初始化为 S4
1.状态机列表为{ S4,S1, S0} S4在栈顶;初始化时先初始化 S0 (进入到S0的enter函数),然后S1 (进入到S0的enter函数),然后S4(进入到S0的enter函数);如果此时有消息,则依次 S4,S1,S0调用processMessage函数

2.如果转换状态,如 转换到 S5,则首先依次按照 S4,S1,S0 调用processMessage函数(如果有消息,此时消息到S0还没有被处理,则该消息将被抛弃掉),然后S4,S1 依次调用exit函数(S0未退出是因为为根节点,在S5-S2-S0这条线上),开始依次初始化 S2,S5(调用 enter函数),当前栈顶变为 S5

3.初始化(enter) S0->S1->S4; 退出(exit) S4->S1->S0;
4.中间过程:状态没有改变,同时processMessage函数返回值为 return super.processMessage(message),则每出现一条 MSG 就按照 S4->S1->S0 调用 processMessage函数
5.中间过程:状态没有改变,同时processMessage函数返回值为 return true (假设S4是这样写的),则每出现一条 MSG 就按照 S4 调用 processMessage函数,S1 S0不会被调用
6.状态没有改变和状态机没有关闭,则一直停留在该状态,等待消息

以上为个人的学习,可能会有错误的地方,如遇到,请指教

五、参考地址:
1.https://www.jianshu.com/p/f3ad78613072
2.https://blog.csdn.net/pi9nc/article/details/27503071

六、上述代码不完整
代码地址:
https://download.csdn.net/download/shiluohuashengmi/10510256

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值