@@ -38,7 +38,7 @@ public static AvatarManager Instance
3838 private readonly Lock _synclock = new ( ) ;
3939 private string _storePath ;
4040 private List < IAvatarHost > _avatars = new List < IAvatarHost > ( ) ;
41- private Dictionary < string , Bitmap > _resources = new Dictionary < string , Bitmap > ( ) ;
41+ private Cache _cache = new Cache ( 256 ) ;
4242 private HashSet < string > _requesting = new HashSet < string > ( ) ;
4343 private HashSet < string > _defaultAvatars = new HashSet < string > ( ) ;
4444
@@ -120,7 +120,7 @@ public void Start()
120120
121121 Dispatcher . UIThread . Post ( ( ) =>
122122 {
123- _resources [ email ] = img ;
123+ _cache . AddOrUpdate ( email , img ) ;
124124 NotifyResourceChanged ( email , img ) ;
125125 } ) ;
126126 }
@@ -146,7 +146,7 @@ public Bitmap Request(string email, bool forceRefetch)
146146 if ( _defaultAvatars . Contains ( email ) )
147147 return null ;
148148
149- _resources . Remove ( email ) ;
149+ _cache . Remove ( email ) ;
150150
151151 var localFile = Path . Combine ( _storePath , GetEmailHash ( email ) ) ;
152152 if ( File . Exists ( localFile ) )
@@ -156,7 +156,7 @@ public Bitmap Request(string email, bool forceRefetch)
156156 }
157157 else
158158 {
159- if ( _resources . TryGetValue ( email , out var value ) )
159+ if ( _cache . TryGet ( email , out var value ) )
160160 return value ;
161161
162162 var localFile = Path . Combine ( _storePath , GetEmailHash ( email ) ) ;
@@ -167,7 +167,7 @@ public Bitmap Request(string email, bool forceRefetch)
167167 using ( var stream = File . OpenRead ( localFile ) )
168168 {
169169 var img = Bitmap . DecodeToWidth ( stream , 128 ) ;
170- _resources . Add ( email , img ) ;
170+ _cache . AddOrUpdate ( email , img ) ;
171171 return img ;
172172 }
173173 }
@@ -197,7 +197,7 @@ public void SetFromLocal(string email, string file)
197197 image = Bitmap . DecodeToWidth ( stream , 128 ) ;
198198 }
199199
200- _resources [ email ] = image ;
200+ _cache . AddOrUpdate ( email , image ) ;
201201
202202 lock ( _synclock )
203203 {
@@ -217,7 +217,7 @@ public void SetFromLocal(string email, string file)
217217 private void LoadDefaultAvatar ( string key , string img )
218218 {
219219 var icon = AssetLoader . Open ( new Uri ( $ "avares://SourceGit/Resources/Images/{ img } ", UriKind . RelativeOrAbsolute ) ) ;
220- _resources . Add ( key , new Bitmap ( icon ) ) ;
220+ _cache . AddOrUpdate ( key , new Bitmap ( icon ) ) ;
221221 _defaultAvatars . Add ( key ) ;
222222 }
223223
@@ -233,5 +233,76 @@ private void NotifyResourceChanged(string email, Bitmap image)
233233 foreach ( var avatar in _avatars )
234234 avatar . OnAvatarResourceChanged ( email , image ) ;
235235 }
236+
237+ private class Cache
238+ {
239+ private readonly int _capacity ;
240+ private readonly LinkedList < Item > _imgList ;
241+ private readonly Dictionary < string , LinkedListNode < Item > > _key2img ;
242+
243+ private class Item
244+ {
245+ public string Key { get ; }
246+ public Bitmap Image { get ; set ; }
247+
248+ public Item ( string key , Bitmap image )
249+ {
250+ Key = key ;
251+ Image = image ;
252+ }
253+ }
254+
255+ public Cache ( int capacity )
256+ {
257+ _capacity = capacity ;
258+ _key2img = new Dictionary < string , LinkedListNode < Item > > ( ) ;
259+ _imgList = new LinkedList < Item > ( ) ;
260+ }
261+
262+ public bool TryGet ( string key , out Bitmap bitmap )
263+ {
264+ if ( _key2img . TryGetValue ( key , out var node ) )
265+ {
266+ _imgList . Remove ( node ) ;
267+ _imgList . AddFirst ( node ) ;
268+ bitmap = node . Value . Image ;
269+ return true ;
270+ }
271+
272+ bitmap = null ;
273+ return false ;
274+ }
275+
276+ public void AddOrUpdate ( string key , Bitmap bitmap )
277+ {
278+ if ( _key2img . TryGetValue ( key , out var node ) )
279+ {
280+ _imgList . Remove ( node ) ;
281+ _imgList . AddFirst ( node ) ;
282+ node . Value . Image = bitmap ;
283+ return ;
284+ }
285+
286+ if ( _key2img . Count >= _capacity )
287+ {
288+ var lastNode = _imgList . Last ;
289+ _imgList . RemoveLast ( ) ;
290+ _key2img . Remove ( lastNode . Value . Key ) ;
291+ }
292+
293+ var newNode = new LinkedListNode < Item > ( new Item ( key , bitmap ) ) ;
294+ _imgList . AddFirst ( newNode ) ;
295+ _key2img [ key ] = newNode ;
296+ }
297+
298+ public void Remove ( string key )
299+ {
300+ if ( _key2img . TryGetValue ( key , out var node ) )
301+ {
302+ _imgList . Remove ( node ) ;
303+ _key2img . Remove ( key ) ;
304+ }
305+ }
306+ }
236307 }
237308}
0 commit comments