演示效果:

需求描述: 在发送礼物按钮上进行连击,界面上展示礼物且礼物数字随着连击事件增加。需求扩展:数字变动的间隔时间可通过参数设置。

思路简析: 这可以看作是一个生产-消费模型,用队列来存储连击事件。什么是状态机思想呢?简单地说,就是n个状态在不同条件下互相转化的过程。那么如何通过状态机思想来分析这个需求呢?

首先,罗列出所有状态:STARTWORKINGWAITINGSTOP
然后画草图,画出状态之间的转换条件:

按照状态机思想画上草图后,状态之间的关系链就会变得很清晰。

源码:

public class ComboUtil<T extends ComboUtil.TimeEvt> {//点击事件队列private LinkedList<T> queue;private ComboHandler<T> mHandler;/*** @param noRspTime       无响应时间 两次点击间隔noRspTime时默认为新一轮连击* @param takeEvtInterval 取队列数据的间隔时间,同一轮连击里点击事件的间隔时间*/public ComboUtil(Callback<T> callback, long noRspTime, long takeEvtInterval) {queue = new LinkedList<>();mHandler = new ComboHandler<T>(callback, noRspTime, takeEvtInterval) {@Overridepublic T takeEvt() {return queue.isEmpty() ? null : queue.removeFirst();}@Overridepublic T getEvt() {return queue.isEmpty() ? null : queue.getFirst();}@Overridepublic boolean isEmptyQueue() {return queue.isEmpty();}};}public void onClick(T evt) {queue.add(evt);Log.d("连击测试", "enqueue");mHandler.onModelEnqueue();}public void onDestroy() {mHandler.onDestroy();queue.clear();}public static class TimeEvt {private long mills;public TimeEvt() {this.mills = System.currentTimeMillis();}public long getMills() {return mills;}}public interface Callback<T> {//连击准备void onStart();//连击回调void onCombo(T evt);//等待点击void onWaiting();//连击结束void onStop();}public static abstract class ComboHandler<T> extends Handler {public static final int START = 1;public static final int WORKING = 2;public static final int STOP = 4;public static final int WAITING = 3;private ComboUtil.Callback<T> callback;private long takeEvtInterval;private long noRspTime;//单位:毫秒public ComboHandler(ComboUtil.Callback<T> callback, long noRspTime, long takeEvtInterval) {this.callback = callback;this.takeEvtInterval = takeEvtInterval;this.noRspTime = noRspTime;}@Overridepublic void handleMessage(Message msg) {//用msg.arg1表示上一个状态int from = msg.arg1;Message newMsg = Message.obtain();switch (msg.what) {case START:if (from < STOP && from >= START) return;//不符合DFA状态机算法图Log.d("连击测试", "receive START msg");newMsg.arg1 = START;if (callback != null)callback.onStart();if (isEmptyQueue()) {newMsg.what = WAITING;//队列为空进入等待状态} else {newMsg.what = WORKING;//进入工作状态}sendMessage(newMsg);break;case WORKING:if (from == WORKING || from == WAITING || from == START) {//符合DFA状态机算法图Log.d("连击测试", "receive WORKING msg");newMsg.arg1 = WORKING;//从队尾取出一个点击事件T t = takeEvt();ComboUtil.TimeEvt evt = (TimeEvt) t;if (evt == null) {//当前队列已空if (from == WAITING) {//上一个状态已经是等待状态了newMsg.what = STOP;sendMessage(newMsg);//直接结束本次连击} else {//进入等待状态newMsg.what = WAITING;sendMessage(newMsg);}} else {if (callback != null)callback.onCombo(t);//判断下一条数据时间ComboUtil.TimeEvt nxtEvt = (TimeEvt) getEvt();if (nxtEvt != null && nxtEvt.getMills() - evt.getMills() >= noRspTime) {//认为本次连击结束,并重新开始新一轮连击newMsg.what = STOP;} else newMsg.what = WORKING;sendMessageDelayed(newMsg, takeEvtInterval);}}break;case WAITING:if (from == START || from == WORKING || from == WAITING) {Log.d("连击测试", "receive WAITING msg");newMsg.arg1 = WAITING;boolean isEmpty = isEmptyQueue();//符合DFA状态机算法图if (callback != null)callback.onWaiting();switch (from) {case START:case WORKING://取数据时发现队列已空,进入等待状态,noRspTime时间后再次判断队列是否为空newMsg.what = WAITING;sendMessageDelayed(newMsg, noRspTime);break;case WAITING:if (isEmpty) {//经过noRspTime后 数据队列仍然为空,直接发送stop msg 结束这次连击newMsg.what = STOP;} else {//经过noRspTime后 数据队列已入队新的数据,发送take msg 继续取数据newMsg.what = WORKING;}sendMessage(newMsg);break;}}break;case STOP:if (from == WORKING || from == WAITING) {Log.d("连击测试", "receive STOP msg");newMsg.arg1 = STOP;if (callback != null)callback.onStop();//发送stop msg到接收stop msg之间可能还有入队操作,需要再检查一次队列if (!isEmptyQueue()) {newMsg.what = START;sendMessage(newMsg);}}break;}}//读写操作public abstract T takeEvt();//只读操作public abstract T getEvt();public abstract boolean isEmptyQueue();//是否是空闲状态public boolean isIDLE() {boolean hasMsg = hasMessages(START) || hasMessages(WORKING) || hasMessages(WAITING) || hasMessages(STOP);return !hasMsg;}/*** 当前空闲 则发送start msg 开始工作* 开始工作后会自动按照逻辑从数据model队列取数据*/public void onModelEnqueue() {if (isIDLE())sendEmptyMessage(START);else if (hasMessages(WAITING)) {//如果是等待状态-唤醒removeMessages(WAITING);Message newMsg = Message.obtain();newMsg.arg1 = WAITING;newMsg.what = WORKING;sendMessage(newMsg);}}public void onDestroy() {removeCallbacksAndMessages(null);if (callback != null)callback.onStop();}}
}

大家有什么好用的制图软件推荐吗?

有任何疑问或建议欢迎留言讨论!

Android-状态机算法思想实现礼物连击需求相关推荐

  1. 【数据结构与算法】【算法思想】贪心算法

    贪心算法 回溯算法 分治算法 动态规划 四种基本的算法思想:贪心算法,分治算法,回溯算法,动态规划,他们不是具体算法,常用来指导我们设计具体的算法和编码等. 一:贪心算法有很多经典应用 霍夫曼编码(H ...

  2. SinglepassTextCluster项目:基于single-pass算法思想的自动文本聚类组件

    项目的背景 SinglepassTextCluster, an TextCluster tool based on Singlepass cluster algorithm that use tfid ...

  3. 递归下降分析法的基本思想。_还不懂这八大算法思想,刷再多题也白搭!

    各位朋友好久不见呢.最近由于刚入职,作为职场萌新,所以大部分时间都花在了工作上.因而也没有太多时间来写文章啦,这篇文章也是定题了许久,迟迟没有落笔.等之后工作慢慢稳定,业务熟练起来,文章更新频率就会高 ...

  4. 道家·老子的算法思想分析

    道家·老子的算法思想分析 在前一篇文章"屈原·渔父的算法追求"中谈到,屈原追求的是高效的算法,而渔父追求的是高可靠性的算法. 对于屈原与渔父的思想,后人通常认为屈原反映了儒家杀身成 ...

  5. 《深入理解Android内核设计思想(第2版)(上下册)》之Android源码下载及编译

    本文摘自人民邮电出版社异步社区<深入理解Android内核设计思想(第2版)(上下册)> 购书地址:http://item.jd.com/12212640.html 试读地址:http:/ ...

  6. 还不懂这八大算法思想,刷再多题也白搭!

    各位朋友好久不见呢.最近由于刚入职,作为职场萌新,所以大部分时间都花在了工作上.因而也没有太多时间来写文章啦,这篇文章也是定题了许久,迟迟没有落笔.等之后工作慢慢稳定,业务熟练起来,文章更新频率就会高 ...

  7. 《深入理解Android内核设计思想(第2版)(上下册)》之Android源码下载及编译...

    本文摘自人民邮电出版社异步社区<深入理解Android内核设计思想(第2版)(上下册)> 购书地址:item.jd.com/12212640.ht- 试读地址:www.epubit.com ...

  8. 深度学习前沿算法思想

    转自: 深度学习前沿算法思想 导读 第一版: 深度学习前沿算法思想 深度学习实践:使用Tensorflow实现快速风格迁移 行为识别:让机器学会"察言观色"第一步 第二版: 谷歌首 ...

  9. 机器学习常见算法思想的面试宝典

    本文转载自机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理) 前言: 找工作时(IT行业),除了常见的软件开发以外,机器学习岗位也可以当作是一个选择,不少计算机方向的研究生都会 ...

最新文章

  1. SecureCRT窗口输出代码关键字高亮设置
  2. 【转】创建SVN仓库的步骤
  3. linux初始化root密码
  4. 光耦驱动单向可控硅_华越国际一文带路:可控硅触发设计技巧
  5. 计算机网络符号显示叹号,在Win7系统中,电脑网络出现感叹号怎么解决?
  6. java string 内存写了_Java String的内存机制
  7. lua mysql 事务_为什么在 Redis 实现 Lua 脚本事务?-阿里云开发者社区
  8. [转载] [Python] np.ones_like(ndarray)和np.zeros_like(ndarray)
  9. 排序算法--冒泡排序
  10. 计算机专业毕业设计的进度记录,毕业设计周次进度计划及实际进展情况表.doc...
  11. 纯H5实现扫码:浏览器扫码
  12. 面试过阿里等互联网大公司,我知道了这些套路
  13. 平面设计基础学习-1
  14. 358. K 距离间隔重排字符串 排序
  15. 逆向爬虫08 并发异步编程
  16. AS608指纹模块简要说明
  17. html2canvas解决图片空白,网络图片跨域
  18. 如何引用电影?(APA、MLA、芝加哥、温哥华格式)
  19. aix kill java_AIX环境Java进程cpu瓶颈分析(转)
  20. Mac字体编辑器哪个好用?FontLab VI for Mac永久激活版分享

热门文章

  1. yolov5模型pt转wk(HISI3559)
  2. mobilefacenet caffe2WK
  3. Oracle数据库基础知识+sql语句练习
  4. python在国内外研究现状_国内外研究现状,水平和发展趋势-开题报告
  5. ElementUI的Table组件在无数据情况下让“暂无数据”文本居中显示
  6. 手机端html跑马灯效果,使用css3和js在手机上实现简单的跑马灯效果
  7. 【庖丁解牛系列】 项目时间管理之前导图/单代号网络图
  8. CMWAP 和 CMNET
  9. 使用 RIBs 重构 Uber 司机端
  10. MUR1660AC-ASEMI超快恢复二极管MUR1660AC