什麼是 『動態數據集合』 ?簡而言之,就是當集合添加、刪除項目或者重置時,能提供一種通知機制,告訴UI動態更新界面。有經驗的程序員腦海裏迸出的第一個詞就是 ObservableCollection。沒錯,它在WPF中盛行其道,經過它開發者能夠很方便的達到動態更新界面。要在Unity 3D中使用ObservableCollection仍是有些許困難的,由於Mono並不提供ObservableCollection類。但實際上,本身動手去構建一個『動態數據集合』也非難事,核心在於怎樣去傳播通知。這也是本篇博客的主題。git
既然核心在於構建通知機制,談到『通知』兩字,最多見的形式就是以委託或者事件形式將消息廣播給監聽者。遺憾的是,.NET中常見的集合數據結構List並不支持事件的通知。因此我在自定義的ObservableList中增長OnAdd,OnRemove,OnInsert事件,當集合添加或者刪除項時,能廣播通知給客戶端UI界面。程序員
如下圖爲例,當點擊+時,『以數據驅動界面的形式』,動態的去更新UI界面:github
既然要以數據來驅動界面,首先咱們須要定義能存放數據的集合,它就是ObservableList,而且是實現了IList 接口:數據結構
public class ObservableList<T>:IList<T>
{
//...省略部分代碼...
private List<T> _value=new List<T>();
public delegate void AddHandler(T instance);
public AddHandler OnAdd;
public delegate void InsertHandler(int index,T instance);
public InsertHandler OnInsert;
public delegate void RemoveHandler(T instance);
public RemoveHandler OnRemove;
public void Add(T item) {
_value.Add(item);
if (OnAdd != null)
{
OnAdd(item);
}
}
public bool Remove(T item) {
if (_value.Remove(item))
{
if (OnRemove != null)
{
OnRemove(item);
}
return true;
}
return false;
}
public void Insert(int index, T item) {
_value.Insert(index,item);
if (OnInsert!=null)
{
OnInsert(index, item);
}
}
}複製代碼
能夠看到,自定義的ObservableList實現了 IList 接口,並以泛型的形式約束了數據項類型。當添加或者刪除項時,提供了以事件的形式告訴客戶端UI界面 ,做爲觀察者的UI能夠順勢作出相應的更新。ui
岔開話題說一下,爲何要用泛型,這是幾天前有同窗在羣裏問的?spa
到目前爲止,咱們自定義的動態數據集合ObservableList是很是好的設計,但惟一不足的事,它不能支持初始化時通知UI界面更新。 『初始化』 這詞可能有點太術語了,我翻譯一下就是通常初始化一個List,咱們都是像以下方式進行:翻譯
public ObservableList<FaceBox> DataSource = new ObservableList<FaceBox>
{
new FaceBox
{
Name = "Eyes",
Level = 10,
Face = "Avatar201_Face",
Badge = new Badge {Icon = "Icon_WeaponRod", ElementColor = "1CB9FFFF"}
},
new FaceBox
{
Name = "Jack",
Level = 8,
Face = "Avatar202_Face",
Badge = new Badge {Icon = "Icon_WeaponSpear", ElementColor = "FF5821FF"}
}
};複製代碼
顯然這即沒有觸發OnAdd,也沒有觸發OnRemove等事件,那麼初始化或者重置列表時,UI界面仍是得不到更新。那咱們怎麼去解決呢?還記得第一章中BindableProperty嗎?對了,解決方案就是它,對列表的初始化或者重置就是對Value進行改變。而BindableProperty內部提供了對Value值改變的監聽,一旦Value改變了,將消息廣播出去。設計
OK,咱們加強一下ObservableList:code
public class ObservableList<T>:IList<T>
{
//省略部分代碼...
public delegate void ValueChangedHandler(List<T> oldValue, List<T> newValue);
public ValueChangedHandler OnValueChanged;
//預先初始化,內置的List,防止空異常
private List<T> _value=new List<T>();
public List<T> Value
{
get { return _value; }
set
{
if (!Equals(_value, value))
{
var old = _value;
_value = value;
ValueChanged(old, _value);
}
}
}
private void ValueChanged(List<T> oldValue, List<T> newValue) {
if (OnValueChanged != null)
{
OnValueChanged(oldValue, newValue);
}
}
}複製代碼
因此客戶端UI界面只要對ObservableList的OnValueChanged事件進行監聽,當初始化或者重置時,你也能夠獲得更新,演示效果以下:cdn
自定義的動態數據集合ObservableList看起來小巧,但五臟俱全,能提供通知機制,能夠動態的去更新UI界面。 全部的一切都以數據的改變來驅動UI,這是很是重要的轉變。因此看似代碼複雜了,但實際上你只要關心數據便可。
源代碼託管在Github上,點擊此瞭解
歡迎關注個人公衆號: