Android 状态机 StateMachine 详解
1、StateMachine 概述
StateMachine 是 Android 框架提供的状态机实现,位于 com.android.internal.util 包中。它基于消息驱动,通过状态模式管理复杂的状态转换逻辑,广泛应用于 Android 系统内部,如 Wifi 状态管理、蓝牙连接管理等。
核心特性:
- 基于消息驱动的状态转换
- 支持状态层级结构
- 提供状态进入、退出、消息处理回调
- 支持延迟消息和定时消息
- 线程安全,支持异步操作
应用场景:
- 网络连接状态管理
- 播放器状态控制
- 业务流程状态管理
- 复杂交互逻辑处理
- 协议解析和状态跟踪
2、核心概念
2.1、State 类
State 是状态机中的基本单元,表示一个具体的状态:
主要方法:
- enter():进入状态时调用
- exit():退出状态时调用
- processMessage(Message msg):处理消息,返回 true 表示已处理
- getName():获取状态名称
2.2、StateMachine 类
StateMachine 是状态机的核心类,负责管理状态和消息:
主要方法:
- addState(State state):添加状态
- addState(State state, State parent):添加层级状态
- setInitialState(State state):设置初始状态
- start():启动状态机
- sendMessage(Message msg):发送消息
- transitionTo(State state):切换状态
- quit():退出状态机
2.3、状态层级
StateMachine 支持状态层级结构,子状态可以继承父状态的消息处理逻辑:
- 父状态可以处理子状态未处理的消息
- 状态切换时,会自动调用 enter() 和 exit()
- 支持多层嵌套的状态结构
3、基本使用方法
3.1、定义状态类
class IdleState extends State {
@Override
public void enter() {
Log.d("StateMachine", "进入空闲状态");
}
@Override
public void exit() {
Log.d("StateMachine", "退出空闲状态");
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case MSG_START:
// 切换到工作状态
transitionTo(mWorkingState);
return true;
}
return false; // 未处理,交给父状态
}
}
class WorkingState extends State {
@Override
public void enter() {
Log.d("StateMachine", "进入工作状态");
startWork();
}
@Override
public void exit() {
Log.d("StateMachine", "退出工作状态");
stopWork();
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case MSG_STOP:
transitionTo(mIdleState);
return true;
case MSG_PAUSE:
transitionTo(mPausedState);
return true;
}
return false;
}
}
3.2、创建状态机
class MyStateMachine extends StateMachine {
private static final int MSG_START = 1;
private static final int MSG_STOP = 2;
private static final int MSG_PAUSE = 3;
private IdleState mIdleState = new IdleState();
private WorkingState mWorkingState = new WorkingState();
private PausedState mPausedState = new PausedState();
public MyStateMachine(String name) {
super(name);
// 添加状态
addState(mIdleState);
addState(mWorkingState);
addState(mPausedState);
// 设置初始状态
setInitialState(mIdleState);
}
public void start() {
start();
}
public void sendMessage(int what) {
sendMessage(obtainMessage(what));
}
}
3.3、使用状态机
MyStateMachine stateMachine = new MyStateMachine("MyStateMachine");
stateMachine.start();
// 发送消息切换状态
stateMachine.sendMessage(MSG_START); // 切换到工作状态
stateMachine.sendMessage(MSG_PAUSE); // 切换到暂停状态
stateMachine.sendMessage(MSG_STOP); // 切换到空闲状态
4、状态转换与消息处理
4.1、状态转换规则
- transitionTo(State):立即切换到目标状态
- 状态切换时会自动调用当前状态的 exit() 和目标状态的 enter()
- 状态切换后,后续消息由新状态处理
4.2、消息处理流程
1. 消息发送到状态机
2. 当前状态处理消息
3. 如果当前状态返回 false,交给父状态处理
4. 如果所有状态都返回 false,消息被丢弃
5. 处理过程中可以调用 transitionTo() 切换状态
4.3、延迟消息
// 发送延迟消息
sendMessageDelayed(obtainMessage(MSG_TIMEOUT), 5000);
// 在状态中处理超时
@Override
public boolean processMessage(Message msg) {
if (msg.what == MSG_TIMEOUT) {
// 处理超时逻辑
transitionTo(mIdleState);
return true;
}
return false;
}
4.4、消息回收
// 移除特定消息
removeMessages(MSG_TIMEOUT);
// 移除所有消息
removeMessages();
5、实际应用场景
5.1、网络连接状态管理
class NetworkStateMachine extends StateMachine {
private DisconnectedState mDisconnectedState = new DisconnectedState();
private ConnectingState mConnectingState = new ConnectingState();
private ConnectedState mConnectedState = new ConnectedState();
public NetworkStateMachine() {
super("NetworkStateMachine");
addState(mDisconnectedState);
addState(mConnectingState);
addState(mConnectedState);
setInitialState(mDisconnectedState);
}
class DisconnectedState extends State {
@Override
public boolean processMessage(Message msg) {
if (msg.what == MSG_CONNECT) {
transitionTo(mConnectingState);
return true;
}
return false;
}
}
class ConnectingState extends State {
@Override
public void enter() {
// 开始连接
connectToServer();
// 设置连接超时
sendMessageDelayed(obtainMessage(MSG_TIMEOUT), 10000);
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case MSG_CONNECTED:
transitionTo(mConnectedState);
return true;
case MSG_TIMEOUT:
case MSG_DISCONNECT:
transitionTo(mDisconnectedState);
return true;
}
return false;
}
}
class ConnectedState extends State {
@Override
public void enter() {
// 连接成功,开始工作
startWork();
}
@Override
public void exit() {
// 断开连接,清理资源
stopWork();
}
@Override
public boolean processMessage(Message msg) {
if (msg.what == MSG_DISCONNECT) {
transitionTo(mDisconnectedState);
return true;
}
return false;
}
}
}
5.2、播放器状态管理
class PlayerStateMachine extends StateMachine {
private IdleState mIdleState = new IdleState();
private PreparedState mPreparedState = new PreparedState();
private PlayingState mPlayingState = new PlayingState();
private PausedState mPausedState = new PausedState();
public PlayerStateMachine() {
super("PlayerStateMachine");
addState(mIdleState);
addState(mPreparedState);
addState(mPlayingState);
addState(mPausedState);
setInitialState(mIdleState);
}
}
6、最佳实践与注意事项
6.1、设计原则
- 每个状态职责单一,避免状态过于复杂
- 合理使用状态层级,提取公共逻辑到父状态
- 状态转换要清晰,避免循环依赖
- 消息处理要及时,避免消息堆积
6.2、性能优化
- 避免在 enter() 和 exit() 中执行耗时操作
- 合理使用延迟消息,及时清理不需要的消息
- 状态机运行在独立线程,注意线程安全
- 避免频繁创建和销毁状态机
6.3、调试技巧
- 在每个状态的 enter() 和 exit() 中添加日志
- 记录状态转换和消息处理过程
- 使用 getName() 标识不同的状态机实例
- 监控消息队列大小,避免内存泄漏
6.4、常见问题
问题1:状态转换死循环
解决:检查 transitionTo() 调用逻辑,避免在 enter() 中立即切换状态
问题2:消息处理不及时
解决:检查是否有耗时操作阻塞消息处理,考虑使用异步处理
问题3:内存泄漏
解决:及时调用 quit() 退出状态机,清理延迟消息
6.5、总结
StateMachine 是 Android 提供的强大状态管理工具,通过消息驱动和状态模式,可以优雅地管理复杂的状态转换逻辑。合理使用 StateMachine 可以使代码结构更清晰,状态管理更可靠。
关键要点:
- 继承 State 定义具体状态
- 继承 StateMachine 创建状态机
- 使用 transitionTo() 切换状态
- 合理使用状态层级结构
- 注意性能优化和内存管理
掌握 StateMachine 的使用,对于开发复杂业务逻辑、网络连接管理、播放器控制等场景非常有帮助,是 Android 高级开发者必备的技能之一。