项目里有代码专门监听网络环境的变化,特别是在下载中,如果遇到断网或者切换为移动网络,可能需要触发提醒等等。这种需求可能是通用的,于是便写了一个通用的监听代码。是
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
public delegate T XValueGetter<T>();
public interface IValueObserver
{
long GetId();
bool Check(long checkTime);
bool ReachCheckTime(long checkTime);
void NotifyChange();
}
public class XValueObserve<T> : IValueObserver
{
public T CurrentValue;
public long LastCheckTime;
public XValueGetter<T> Getter { get; set; }
public Action<T> OnValueChangeCallback { get; set; }
public long CheckInterval;
public long Id;
public XValueObserve(long id, XValueGetter<T> getter, Action<T> onValueChangeCallback, long checkInterval)
{
Id = id;
Getter = getter;
OnValueChangeCallback = onValueChangeCallback;
CheckInterval = checkInterval;
LastCheckTime = 0;
CurrentValue = getter();
}
public long GetId()
{
return Id;
}
public bool ReachCheckTime(long checkTime)
{
return checkTime - LastCheckTime >= CheckInterval;
}
public bool Check(long checkTime)
{
T currentValue = Getter();
LastCheckTime = checkTime;
if (!currentValue.Equals(CurrentValue))
{
CurrentValue = currentValue;
return true;
}
return false;
}
public void NotifyChange()
{
OnValueChangeCallback?.Invoke(CurrentValue);
}
}
public class XValueObserveManager
{
private static Stopwatch s_stopWatch;
private static long s_observerId;
private static List<IValueObserver> s_observers;
public static void Init()
{
s_observers = new List<IValueObserver>();
s_stopWatch = new Stopwatch();
s_observerId = 0;
}
public static void Start()
{
s_stopWatch.Start();
}
public static void Update()
{
foreach (IValueObserver observer in s_observers)
{
if (observer.ReachCheckTime(s_stopWatch.ElapsedMilliseconds))
{
if (observer.Check(s_stopWatch.ElapsedMilliseconds))
{
observer.NotifyChange();
}
}
}
}
public static long AddObserve<T>(XValueGetter<T> getter, Action<T> onValueChangeCallback, long checkInterval)
{
XValueObserve<T> observe = new XValueObserve<T>(s_observerId++, getter, onValueChangeCallback, checkInterval);
s_observers.Add(observe);
return observe.Id;
}
public static void RemoveObserve(long id)
{
s_observers.RemoveAll(observe => observe.GetId() == id);
}
}
使用起来,也比较方便
void Start()
{
XValueObserveManager.Init();
XValueObserveManager.Start();
int posObserverId = XValueObserveManager.AddObserve(() => transform.position, pos =>
{
Debug.Log(pos);
}, 1000);
int netObserverId = XValueObserveManager.AddObserve(() => Application.internetReachability, reach =>
{
Debug.Log(reach.ToString());
}, 1000);
}
注意,这种变化观察都是非及时性质的,也就是并不会在变化发生的瞬间通知,而是最少要延迟一帧(基于Update执行)。
如果需要的是实时的,则需要另外的设计了,比如用事件管理器,但对于一些通用的数值则可能需要封装为属性,重载set方法,广播事件了。
翻译
搜索
复制