Xamarin Xamarin Forms Prsim

Xamarin Forms Prism 訂閱與發佈EventAggregator

張阿鬼 2019/12/27 19:37:04
1866

Prism提供了一個事件聚合器之機制,
透過事件聚合器進行訂閱以及發佈,
讓每個模組或功能的耦合性降低提高維護性。

Prism提供的這組訂閱/發佈機制與Xamarin Forms本身的MessagingCenter其實非常類似,
不知道MessagingCenter的可以參考:
https://docs.microsoft.com/zh-tw/xamarin/xamarin-forms/app-fundamentals/messaging-center

不過Prism所提供的事件聚合器功能較完整,使用也較方便。
Prism的事件聚合器是讓訂閱者或發布者去查找特定的EventBase類型,
並且允許多個發布者跟多個訂閱者。如下圖示意:


取得聚合器EventAggregator
EventAggregator在Prism中一開始就會被保留服務在IoC容器中,
並且以IEventAggregator這個介面提供使用。
要使用的時候只要在建構子宣告傳入類型為IEventAggregator的參數即可取得聚合器物件

        public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
            : base(navigationService)
        {
        }

訂閱事件
不論是訂閱事件還發佈事件,
都是以特定的EventBase類型做為Key去查找,
所以我們需先定義一個自己的EventBase類型,
我們繼承使用已實做的PubSubEvent<T>,T表示該訂閱的事件會拿到類型T的參數。

    public class MyEvent: PubSubEvent<string>
    {

    }

接著當我們要訂閱類型為MyEvent的事件時,可以透過聚合器使用Subscribe方法做訂閱,arg即為發佈者傳遞來的參數:

        public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
            : base(navigationService)
        {
            eventAggregator.GetEvent<MyEvent>().Subscribe(arg =>
            {
                this.Text = arg;
            });

 

發佈事件
當我們要發佈事件給上述的訂閱程式,
同樣也必須使用MyEvent類別做發佈,
不然不同類型可是會發不到給訂閱者的喔。
這裡使用Publish方法進行發佈事件。

            this.OnFire = new DelegateCommand(() =>
              {
                  eventAggregator.GetEvent<MyEvent>().Publish("我是訂閱通知");


執行序選擇
當訂閱者事件被觸發時,
可以在Subscribe方法中選擇要在哪個執行序做觸發。
假設我們要讓它在UI執行序上,可撰寫如下程式碼

            eventAggregator.GetEvent<MyEvent>().Subscribe(arg =>
            {
                this.Text = arg;
            }, ThreadOption.UIThread);

ThreadOption列舉提供了三種
  UIThread:在UI執行序上運行。
  PublisherThread:與發佈者相同的執行序運行,預設值。
  BackgroundThread:在背景執行序運行。

 

使用強型別事件參考
預設的情況下,訂閱是使用弱型別參考使用事件(weak reference ),
使用弱型別參考的方式使用者不需要取消訂閱,
系統還是會回收不再使用的記憶體。
但如果有短時間內大量發送事件給訂閱者的狀況時,
弱型別參考的方式可能就會有效能問題,
這時我們可以增加傳入一個布林值參數讓它變為強型別參考。

            eventAggregator.GetEvent<MyEvent>().Subscribe(arg =>
            {
                this.Text = arg;
            }, ThreadOption.BackgroundThread,true);

但如果使用了強型別參考,就要在不需要使用的時候進行取消訂閱的動作,
系統才有辦法正確地進行記憶體回收的機制,
否則可能會導致記憶體洩漏的問題(memory leak)。

取消訂閱
當我們不需要再接收訂閱的事件時,可以透過Unsubscribe方法取消訂閱。

   //...   
      eventAggregator.GetEvent<MyEvent>().Subscribe(EventFire);

        }
        public void EventFire(string arg)
        {
            this.Text = arg;
            _eventAggregator.GetEvent<MyEvent>().Unsubscribe(EventFire);
        }

 

簡單的完成範例,按下按鈕發送訂閱,
收到訂閱後更改文字並且取消訂閱。


範例連結
https://github.com/stevenchang0529/Xamarin.Lab.PrismEventAggregator

 

張阿鬼