之前做多语言相关需求的时候,为了保证每次切换语言,所有的控件都可以监听到语言变化事件,我在多语言组件上添加了一组注册和移除事件的监听:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
protected virtual void OnDestroy() { if (listenerOpen) { LanguageManager.LocalizationChangeEvent -= UpdateContent; } } protected void OpenLanguageListener() { if (!listenerOpen) { LanguageManager.LocalizationChangeEvent += UpdateContent; } } |
但是最近在uwa测试的时候发现这个OnDestory函数居然会导致超超超高的GC。
主要原因还是在将函数注册到回调的时候,会创建一个MulticastDelegate的对象,而这个对象的频繁创建与移除,就会导致大量的GC。尤其是像多语言组件这种每个Text和每个Image组件都会附带的组件来说,在关闭UI界面的时候,会有大量的多语言组件取消回调,就会导致GC过高。
调用3次就有3.7KB的GC了~,每次调用都有超过1KB的GC!
解决方案:对事件回调进行缓存,通过自己手动调用来避免频繁的增删:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//----------------------before---------------------- // Before: You have a reference to a delegate MyDelegate myDelegate; // Before: Combine/Remove delegates myDelegate += MyFunction; myDelegate -= MyFunction; // Before: Call delegate myDelegate(); //----------------------after---------------------- // After: You have a list of delegate references List<MyDelegate> myDelegateList = new List<MyDelegate>(); // After: Add/Remove cached delegate references from the list myDelegateList.Add(cachedDelegateOfMyFunction); myDelegateList.Remove(cachedDelegateOfMyFunction); // After: Call all delegates in list for (int i = 0; i < myDelegateList.Count; ++i) { myDelegateList[i](); } |