HarmonyOS技术社区 · 2020年11月06日

实现物理按键的“长按事件”(按键通用框架 V0.0.2)

我在之前的帖子《实现按键“按下事件”和“释放事件”的通用框架(V0.0.1)》中阐述了DTButton-V0.0.1的设计思路,并且也在帖子中开源了实现代码。

实现这个框架的意图非常明显,就是为了偷懒,想要响应按键事件的时候可以一行代码搞定。也正是因为只想偷懒,V0.0.1版本在实现上非常的简单粗暴:快速实现功能即可,其它问题暂时不考虑。

核心实现代码如下:
图片.png

有同学可能会说:这样实现有什么问题吗?看起来合情合理,用起来也没问题啊!

是的!从功能实现角度,这样做是最简单的,代码量最少,能立即可用。然而,大家也需要意识到:OnButtonPressed() 和 OnButtonReleased() 是在中断上下文中调用的!因此,这两个函数必须快速返回,不能做过于繁重的工作。但是作为框架,这两个中断函数又必须调用相应的回调函数。。。这样子的话,就要求传入的回调函数必须短小精悍,不能过于繁琐!!于是,V0.0.1版本的实现短板就凸显了:当按键按下后需要做的处理必须足够简单,如果比较复杂和繁琐,就可能造成系统中断响应不及时,进而导致系统PANIC重启!!!(如果不了解中断的概念,可自行查阅相关资料,也可以看看我的操作系统视频课程。)

那么有没有办法解决这个问题呢?

办法当然是有的!!既然V0.0.1版本的问题和中断响应相关,那么可以借鉴Linux内核中的原则和方案:中断服务程序的执行越快越好,将中断处理分为两部分:中断处理上半部和中断处理下半部。

解释:

中断发生后需要立即调用中断服务程序进行中断处理,如果直接在中断服务程序中做这个处理,那么处理速度必须越快越好!

但是,肯定有一些情况的处理步骤是比较耗时和复杂的,在这种情况下,就可以先把要做的处理工作进行标记(中断上半部),具体处理步骤在中断服务程序返回后再完成(中断下半部)。

是不是感觉很抽象,理解不了了?! 没关系,我们通过V0.0.2版本的设计实现给大家讲解这个方案。

图片.png

上图中的示例就是DTButton - V0.0.2的核心实现,现在应该感觉很简单了吧。嘿嘿!因为是通用框架,所以最终的代码实现要考虑的东西很多,比上图中的示例看起来要复杂些。

现在,这个框架比起上一个版本有了很大的改进,并且还拥有了专用的事件处理线程!也正是因为创建了这个线程,所以不能浪费啊,必须多多利用才行。

那么还能用它来干点啥呢???

大家想想,现在能够捕捉到按键的按下事件和释放事件了!!

那么,如果按下事件和释放事件之间的时间间隔比较长,那么是不是我们就可以“创造“一个全新的长按事件呢???

答案是肯定的!

按下事件发生后,可以通过事件处理线程进行粗略计时,当计时超过预设的时间间隔(大概2.5秒),即可触发长按事件,具体表现为长按事件回调函数的调用。

图片.png

这里需要注意:

  1. 长按事件只会触发一次,即:OnButtonLongPressed() 回调函数只会调用一次
  2. 释放事件触发时需要停止计时,即:按下事件和释放事件之间的时间间隔不足2.5秒就不会触发长按事件

有了上面的分析,大家就可以自己尝试动手实现了。

什么?觉得麻烦?

没事!我已经将实现代码上传到了文末的附件中,大家可以下载使用和研究,非常欢迎大家的意见和建议。

使用示例如下:

1、定义按键事件回调函数
图片.png

2、一键注册,开箱即用
图片.png

运行结果如下:
图片.png

后记:

开箱使用之后,相信已经有同学发现了问题:GPIO_5居然对应了Hi3861上的 3 个物理按键!!!!

怎么解决?

嗯,这是 DTButton - V0.0.3 中会重点解决的问题!

希望大家关注这个框架,我会尽力开发,维护和完善它!

Enjoy it!

获取原文中资源包


作者:唐佐林
想了解更多内容,请访问:
51CTO和华为官方战略合作共建的鸿蒙技术社区
https://harmonyos.51cto.com#jssq

推荐阅读
关注数
3010
内容数
446
华为鸿蒙相关技术,活动及资讯,欢迎关注及加入创作
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息