工作中设计到状态模式的功能是系统升级,在没有认识状态模式时,实现系统升级的功能,就是使用一大堆的int型来表示状态,如正在检查版本,检查失败,检查成功,下载中,下载失败,下载成功,系统更新中,更新失败,更新成功等。然后使用大量的if语句来判断状态后来继续后续的操作。
假如要添加一种状态,比如在升级前要检查rom包的状态,检测不成功清除所有数据重新开始,检测成功则开始升级。这时就需要大量修改代码,带来扩展上的困难,同时维护也比较麻烦。
首先看状态转换关系:
(1)检查版本:两种状态,失败或者成功。
(2)下载:当检查版本成功后,才能下载,下载成功或者失败。
(3)验证:当下载成功后,才能验证,验证失败或者成功。
(4)更新:当验证成功后,才能更新,更新失败或者成功。
使用状态模式设计,定义一个基类,包括检查,下载,验证,更新方法,提供给具体的状态继承实现。
package com.common.update;
public abstract class State {
public void checkVersion() {
// do nothing
}
public void download() {
// do nothing
}
public void update() {
// do nothing
}
public void verify() {
// do nothing
}
}
定义一个UpdateMachine,处理状态变换的具体逻辑,当检查,下载,验证,更新的具体操作会放在一个工作线程中,状态变化全部放在主线程中。
package com.common.update;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
/**
* @author minghuang
*
* 创建一个工作线程用来检查版本,下载,更新。
*/
public class UpdateMachine {
private static volatile UpdateMachine sInstance;
// 主线程
private Handler mMainHandler;
// 工作线程
private HandlerThread mWorkerThread;
private Handler mWorkerHandler;
// 以下状态在主线程上赋值
// 无状态
private State mNoState = new NoState();
// 检查版本的状态
private State mCheckingState = new CheckingState();
private State mCheckSuccessState = new CheckSucessState();
private State mCheckFailedState = new CheckFailedState();
// 下载的状态
private State mDownloadingState = new DownloadingState();
private State mDownloadSuccessState = new DownloadSuccessState();
private State mDownloadFailedState = new DownloadFailedState();
// 验证升级更新文件的状态
private State mVerifyingState = new VerifyingState();
private State mVerifySuccessState = new VerifySuccessState();
private State mVerifyFailedState = new VerifySuccessState();
// 升级更新的状态
private State mUpdatingState = new UpdatingState();
private State mUpdateSuccessState = new UpdateSuccessState();
private State mUpdateFailedState = new UpdateFailedState();
// 保存前一个状态
private State mPreState = null;
// 保存当前状态
private State mState = null;
// 主线程上工作
private boolean mIsWorking = false;
private UpdateMachine() {
mMainHandler = new Handler();
mWorkerThread = new HandlerThread("worker thread");
mWorkerThread.start();
mWorkerHandler = new Handler(mWorkerThread.getLooper());
setState(mNoState);
}
public static UpdateMachine getInstance() {
if (sInstance == null) {
synchronized (UpdateMachine.class) {
if (sInstance == null) {
sInstance = new UpdateMachine();
}
}
}
return sInstance;
}
// 主线程上工作
public void checkVersion() {
if (!isWorking()) {
setState(mCheckingState);
}
mState.checkVersion();
}
// 主线程上工作
public void download() {
if (!isWorking() && mState == mCheckSuccessState) {
setState(mDownloadingState);
}
mState.download();
}
// 主线程上工作
public void verify() {
if (!isWorking() && mState == mDownloadSuccessState) {
setState(mVerifyingState);
}
mState.verify();
}
// 主线程上工作
public void updateWithoutVerify() {
if (!isWorking()
&& (mState == mDownloadSuccessState || mState == mVerifySuccessState)) {
setState(mUpdatingState);
}
mState.update();
}
// 主线程上工作
public void updateAfterVerify() {
if (!isWorking() && mState == mVerifySuccessState) {
setState(mVerifyingState);
}
mState.verify();
}
private void notifyCheckResult(final boolean success) {
Runnable r = new Runnable() {
@Override
public void run() {
setState(success ? mCheckSuccessState : mCheckFailedState);
}
};
runOnMainThread(r);
}
private void notifyDownloadProgress(final int progress) {
Runnable r = new Runnable() {
@Override
public void run() {
}
};
runOnMainThread(r);
}
private void notifyDownloadResult(final boolean success) {
Runnable r = new Runnable() {
@Override
public void run() {
setState(success ? mDownloadSuccessState : mDownloadFailedState);
}
};
runOnMainThread(r);
}
private void notifyUpdateResult(final boolean success) {
Runnable r = new Runnable() {
@Override
public void run() {
setState(success ? mUpdateSuccessState : mUpdateFailedState);
}
};
runOnMainThread(r);
}
private void notifyVerifyResult(final boolean success) {
Runnable r = new Runnable() {
@Override
public void run() {
setState(success ? mVerifySuccessState : mVerifyFailedState);
if (success) {
updateAfterVerify();
}
}
};
runOnMainThread(r);
}
private void notifyIsWorking(final boolean isWorking) {
Runnable r = new Runnable() {
@Override
public void run() {
mIsWorking = isWorking;
}
};
runOnMainThread(r);
}
private void runOnMainThread(Runnable r) {
if (mWorkerThread.getThreadId() == Process.myTid()) {
mMainHandler.post(r);
} else {
r.run();
}
}
private void runOnWorkerThread(Runnable r) {
if (mWorkerThread.getThreadId() == Process.myTid()) {
r.run();
} else {
mWorkerHandler.post(r);
}
}
public boolean isWorking() {
return mIsWorking;
}
public void setState(State state) {
mPreState = mState;
mState = state;
}
public State getState() {
return mState;
}
class NoState extends State {
}
class CheckingState extends State {
@Override
public void checkVersion() {
notifyIsWorking(true);
Runnable r = new Runnable() {
@Override
public void run() {
boolean success = false;
// check before
// do something
// check after
notifyCheckResult(success);
notifyIsWorking(false);
}
};
runOnWorkerThread(r);
}
}
class CheckSucessState extends State {
}
class CheckFailedState extends State {
}
class DownloadingState extends State {
@Override
public void download() {
notifyIsWorking(true);
Runnable r = new Runnable() {
@Override
public void run() {
boolean success = false;
int progress = 0;
// download before
notifyDownloadProgress(progress);
// download after
notifyDownloadResult(success);
notifyIsWorking(false);
}
};
runOnWorkerThread(r);
}
}
class DownloadSuccessState extends State {
}
class DownloadFailedState extends State {
}
class VerifyingState extends State {
@Override
public void verify() {
notifyIsWorking(true);
Runnable r = new Runnable() {
@Override
public void run() {
boolean success = false;
// verify before
// do something
// verify after
notifyVerifyResult(success);
notifyIsWorking(false);
}
};
runOnWorkerThread(r);
}
}
class VerifySuccessState extends State {
}
class VerifyFailedState extends State {
}
class UpdatingState extends State {
@Override
public void update() {
notifyIsWorking(true);
Runnable r = new Runnable() {
@Override
public void run() {
boolean success = false;
// update before
// do something
// update after
notifyUpdateResult(success);
notifyIsWorking(false);
}
};
runOnWorkerThread(r);
}
}
class UpdateSuccessState extends State {
}
class UpdateFailedState extends State {
}
}
状态模式的定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。