原链接:UWP忽略短时间内重复触发的事件 - 超威蓝火

做移动端开发的可能都会遇到这种需求,当用户点击一个按钮之后,由于没有异步,或者设备性能很差等等原因,程序卡住了。但是用户不知道是咋回事啊,就开始狂点按钮,结果请求很多次资源,或者构造了很多重复视图。安卓上有很多介绍如何忽略重复点击的情况,uwp里我好像还没找到,那接下来就说一说我的方法吧。

首先是官方最常用的,从Windows诞生之初用到现在的,点击按钮之后把他Disable掉,等完成了在Enable。其实这算是最好的选择了,但是总归是麻烦了一些,尤其是在MVVM的时候,每个Button都要单独绑定一个IsEnabled,所以接下来就仿照安卓上的通用处理方法试一下。

首先创建一个类,我们就叫他EventWaiter吧,里面维护一个LastTime,一个IsEnabled,事件可以判断这个IsEnabled来知道,上一次点击和这一次点击的间隔是不是过短,从而决定是否要执行。

public class EventWaiter
{
private DateTime _lastTime; public EventWaiter(double seconds)
{
Interval = TimeSpan.FromSeconds(seconds);
} public EventWaiter(TimeSpan interval)
{
Interval = interval;
} public EventWaiter()
{
Interval = TimeSpan.FromSeconds(0.1d);
} //间隔
public TimeSpan Interval { get; set; } public bool IsEnabled
{
get
{
if(DateTime.Now - _lastTime > Interval)
{
_lastTime = DateTime.Now;
return true;
}
return false;
}
} public void Reset()
{
_lastTime = DateTime.Now;
}
}

大概用法是这样的:


var waiter = new EventWaiter(); var button = new Button();
button.Click += OnClick; private void OnClick(object sender,RoutedEventArgs e)
{
if(waiter.IsEnabled)
{
//do something
}
}

接下来就是第三种需求了。对于安卓iOS来说,很少有SizeChanged,但是UWP不一样啊,UWP能窗口运行啊,所以在一些要响应SizeChanged,在窗口大小改变的时候做一些很重操作的时候,拖拽窗口就会变得非常卡,所以我现在想忽略拖动窗口的中间过程,只让他响应最后状态。而上面的EventWaiter,是一段时间内只响应第一次事件的触发,和我们的需求是完全反着的。

这时候就要请救星:DispatcherTimer出来了(感谢小竹)。

大致思路呢,按时间顺序叙述,是当原事件触发时,让Timer开始运行;第二次触发事件时判断Timer是否运行,如果正在运行呢,就停掉重新启动,相当于重置了计时器;等Timer第一次跑完,执行Tick的时候停掉Timer,并且激活内部的事件去做真正的操作。

我们再弄个新的类,起个名字叫EventDelayer(原谅我起名困难),里面需要维护一个DispatcherTimer,还要一个事件Arrived负责在最后被触发,和一个Delay()方法,负责进入触发判断。

public class EventDelayer
{
private DispatcherTimer _timer; public EventDelayer(double seconds) : this(TimeSpan.FromSeconds(seconds))
{
} public EventDelayer(TimeSpan interval)
{
_timer = new DispatcherTimer();
_timer.Tick += _timer_Tick;
Interval = interval;
} public EventDelayer() : this(0.1)
{
} public TimeSpan Interval
{
get => _timer.Interval;
set => _timer.Interval = value;
} public bool ResetWhenDelayed { get; set; } public void Delay()
{
if (!_timer.IsEnabled)
{
_timer.Start();
}
else
{
if (ResetWhenDelayed)
{
_timer.Stop();
_timer.Start();
}
}
} private void _timer_Tick(object sender, object e)
{
if (_timer.IsEnabled)
{
_timer.Stop();
}
OnArrived();
} public event EventHandler Arrived;
protected void OnArrived()
{
Arrived?.Invoke(this, EventArgs.Empty);
} }

用法大概是这个样子:

var delayer = new EventDelayer();

delayer.Arrived += OnArrived;

this.SizeChanged += OnSizeChanged;

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
delayer.Delay();
} private void OnArrived(object sender,EventArgs args)
{
//do something
}

炒鸡完美。github:https://github.com/cnbluefire/ReaderView/tree/master/ReaderView/Common/Helpers

最新文章

  1. js 获取鼠标选中值
  2. 系统hosts文件的作用
  3. 简单理解dropout
  4. Domion OA 日记
  5. ASP.Net 验证控件 RangeValidator
  6. Hadoop Configuration
  7. C# WinForm 上传图片,文件到服务器的方法Uploader.ashx
  8. uvalive 4973 Ardenia
  9. DBHelper 类(网上收集)
  10. 十二、享元(Flyweight)模式--结构模式(Structural Pattern)
  11. vs调试时底部输出调试信息“无法查找或打开 PDB 文件”解决办法
  12. 团队作业4——第一次项目冲刺(Alpha版本)4.26
  13. HDU2688-Rotate
  14. 使用xUnit为.net core程序进行单元测试(4)
  15. Xamarin.Android 使用AsyncTask提示上传动态
  16. APM飞控学习之路的资料
  17. jQuery 嵌套 event 会触发多次的原因
  18. JavaScript·cookie
  19. linux同步Internet时间
  20. 分形之龙形曲线(Dragon Curve)

热门文章

  1. airbnb 开源reAir 工具 用法及源码解析(一)
  2. js 模拟css3 动画1
  3. 深度学习VS机器学习——到底什么区别
  4. SQL Server 磁盘请求超时的833错误原因分析以及解决
  5. javaScript+html5实现图片拖拽
  6. 2018面向对象程序设计(Java)第18周学习指导及要求
  7. hbase--知识点总结2
  8. C++重写(覆盖)、重载、重定义、
  9. 9. Palindrome Number (JAVA)
  10. TPL DataFlow初探(二)