HarmonyOS 鸿蒙Next c#开发的ref和watch实现--轻松完成响应式开发--

发布于 1周前 作者 sinazl 来自 鸿蒙OS

HarmonyOS 鸿蒙Next c#开发的ref和watch实现–轻松完成响应式开发–

using System;
using System.Collections.Generic;

public class Observable { private readonly Dictionary<string, List<Action<object, object>>> _propertyObservers = new();

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> ObservableProperty&lt;T&gt; Ref&lt;T&gt;(T initialValue, <span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName)
{
    <span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> ObservableProperty&lt;T&gt;(initialValue, <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>, propertyName);
}

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> ObservableList&lt;T&gt; RefList&lt;T&gt;(IList&lt;T&gt; initialValue, <span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName)
{
    <span class="hljs-keyword"><span class="hljs-keyword">var</span></span> list = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> ObservableList&lt;T&gt;(initialValue, <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>, propertyName);
    <span class="hljs-keyword"><span class="hljs-keyword">return</span></span> list;
}

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Watch</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName, Action&lt;<span class="hljs-keyword"><span class="hljs-keyword">object</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">object</span></span>&gt; callback)
{
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!_propertyObservers.ContainsKey(propertyName))
    {
        _propertyObservers[propertyName] = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> List&lt;Action&lt;<span class="hljs-keyword"><span class="hljs-keyword">object</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">object</span></span>&gt;&gt;();
    }

    _propertyObservers[propertyName].Add(callback);
}

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">Unwatch</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName, Action&lt;<span class="hljs-keyword"><span class="hljs-keyword">object</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">object</span></span>&gt; callback)
{
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (_propertyObservers.ContainsKey(propertyName))
    {
        _propertyObservers[propertyName].Remove(callback);
    }
}

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">NotifyPropertyChange</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName, <span class="hljs-keyword"><span class="hljs-keyword">object</span></span> oldValue, <span class="hljs-keyword"><span class="hljs-keyword">object</span></span> newValue)
{
    <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (_propertyObservers.TryGetValue(propertyName, <span class="hljs-keyword"><span class="hljs-keyword">out</span></span> <span class="hljs-keyword"><span class="hljs-keyword">var</span></span> callbacks))
    {
        <span class="hljs-keyword"><span class="hljs-keyword">foreach</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">var</span></span> callback <span class="hljs-keyword"><span class="hljs-keyword">in</span></span> callbacks)
        {
            callback?.Invoke(oldValue, newValue);
        }
    }
}

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

public class ObservableProperty<T> { private T _value; private readonly Observable _observable; private readonly string _propertyName;

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-title">ObservableProperty</span></span>(T initialValue, Observable observable, <span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName)
{
    _value = initialValue;
    _observable = observable;
    _propertyName = propertyName;
}

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-keyword"><span class="hljs-keyword">string</span></span> PropertyName =&gt; _propertyName;

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> T Value
{
    <span class="hljs-keyword"><span class="hljs-keyword">get</span></span> =&gt; _value;
    <span class="hljs-keyword"><span class="hljs-keyword">set</span></span>
    {
        <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!EqualityComparer&lt;T&gt;.Default.Equals(_value, <span class="hljs-keyword"><span class="hljs-keyword">value</span></span>))
        {
            T oldValue = _value;
            _value = <span class="hljs-keyword"><span class="hljs-keyword">value</span></span>;
            _observable.NotifyPropertyChange(_propertyName, oldValue, <span class="hljs-keyword"><span class="hljs-keyword">value</span></span>);
        }
    }
}

} public class ObservableList<T> : Collection<T> { private readonly Observable _observable; private readonly string _propertyName;

<span class="hljs-keyword"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-title">ObservableList</span></span>(IList&lt;T&gt; list, Observable observable, <span class="hljs-keyword"><span class="hljs-keyword">string</span></span> propertyName)
    : <span class="hljs-title"><span class="hljs-title">base</span></span>(list)
{
    _observable = observable;
    _propertyName = propertyName;
}

<span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">InsertItem</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">int</span></span> index, T item)
{
    <span class="hljs-keyword"><span class="hljs-keyword">base</span></span>.InsertItem(index, item);
    NotifyChange();
}

<span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">SetItem</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">int</span></span> index, T item)
{
    T oldItem = Items[index];
    <span class="hljs-keyword"><span class="hljs-keyword">base</span></span>.SetItem(index, item);
    NotifyChange(oldItem, item);
}

<span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">RemoveItem</span></span>(<span class="hljs-keyword"><span class="hljs-keyword">int</span></span> index)
{
    T item = Items[index];
    <span class="hljs-keyword"><span class="hljs-keyword">base</span></span>.RemoveItem(index);
    NotifyChange(item, <span class="hljs-keyword"><span class="hljs-keyword">default</span></span>(T)); <span class="hljs-comment"><span class="hljs-comment">// 使用 default(T) 来代表 null</span></span>
}

<span class="hljs-keyword"><span class="hljs-keyword">protected</span></span> <span class="hljs-keyword"><span class="hljs-keyword">override</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">ClearItems</span></span>()
{
    <span class="hljs-keyword"><span class="hljs-keyword">var</span></span> oldItems = Items.ToList(); <span class="hljs-comment"><span class="hljs-comment">// 将 Items 转换为 List&lt;T&gt;</span></span>
    <span class="hljs-keyword"><span class="hljs-keyword">base</span></span>.ClearItems();
    NotifyChange(oldItems, <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> List&lt;T&gt;());
}

<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">NotifyChange</span></span>(T oldValue, T newValue)
{
    _observable.NotifyPropertyChange(_propertyName, oldValue, newValue);
}

<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">NotifyChange</span></span>()
{
    _observable.NotifyPropertyChange(_propertyName, <span class="hljs-keyword"><span class="hljs-keyword">null</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">null</span></span>);
}

<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span> <span class="hljs-title"><span class="hljs-title">NotifyChange</span></span>(List&lt;T&gt; oldValues, List&lt;T&gt; newValues)
{
    _observable.NotifyPropertyChange(_propertyName, oldValues, newValues);
}

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

使用方法:
   

public Observable _observable = new Observable();<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

对于只是监听对象的变化而不去关注某一项的变化的话可以使用如下方式:

    public ObservableProperty<string> Time { get; set; }
       public PlayerCompany()

    {

        Time = _observable.Ref(“Initial Time”, nameof(Time));

    }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>


我这段使用的是单例模式,所以用了一个构造函数,这样方便管理与维护
如果力邀使用较为特殊的情况,需要监听每一项值得变化得话你可以使用如下方式:

    public ObservableList<Employee> Mangers { get; set; }
    public PlayerCompany()

    {

        Mangers = _observable.RefList(new List<Employee> { null},nameof(Mangers));

    }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>


上面得方式是注册一个被观察对象放在观察列表中,那么下面将告诉你如何使用watch了。

 PlayerCompany.Instance._observable.Watch(nameof(PlayerCompany.Time), _timeChangeCallback = (oldValue, newValue) =>
{

});<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

这个watch提供了两个参数,第一个就是注册被观察对象得键值,第二个是一个回调函数,这个回调函数给定一个改版之前得值和改变之后的值。
如果是要关注每一项值的变化注册的被观察对象那么虽然使用的都是watch但是oldValue和newValue给的值并不是所有的值都给,而是哪一个值发生了改变哪一个值就会被单独拎出来通过oldValue和newValue返回新旧的值。
当然,考虑到性能问题,所以提供了Unwatch函数,就是用来随时关闭侦听的,性能问题就会根据使用场景而变化了。
 



关于HarmonyOS 鸿蒙Next c#开发的ref和watch实现–轻松完成响应式开发–的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

回到顶部