SerialBitmapReferenceCounter.java revision ac28599e2b40e0dd6b97f6a91849585531264622
1package com.bumptech.glide.load.engine.bitmap_recycle;
2
3import android.graphics.Bitmap;
4
5import java.util.LinkedList;
6import java.util.Map;
7import java.util.WeakHashMap;
8
9public class SerialBitmapReferenceCounter implements BitmapReferenceCounter {
10
11    private static class InnerTrackerPool {
12        private LinkedList<InnerTracker> pool = new LinkedList<InnerTracker>();
13
14        public InnerTracker get() {
15            InnerTracker result = pool.poll();
16            if (result == null) {
17                result = new InnerTracker();
18            }
19
20            return result;
21        }
22
23        public void release(InnerTracker innerTracker) {
24            pool.offer(innerTracker);
25        }
26    }
27
28    private static class InnerTracker {
29        private int refs = 0;
30
31        public void acquire() {
32            refs++;
33        }
34
35        public boolean release() {
36            refs--;
37
38            return refs == 0;
39        }
40    }
41
42    private final Map<Bitmap, InnerTracker> counter = new WeakHashMap<Bitmap, InnerTracker>();
43    private final BitmapPool target;
44    private final InnerTrackerPool pool = new InnerTrackerPool();
45
46    public SerialBitmapReferenceCounter(BitmapPool target) {
47        this.target = target;
48    }
49
50    private void initBitmap(Bitmap toInit) {
51        final InnerTracker tracker = counter.get(toInit);
52        if (tracker == null) {
53            counter.put(toInit, pool.get());
54        }
55    }
56
57    @Override
58    public void acquireBitmap(Bitmap bitmap) {
59        initBitmap(bitmap);
60        counter.get(bitmap).acquire();
61    }
62
63    @Override
64    public void releaseBitmap(Bitmap bitmap) {
65        final InnerTracker tracker = counter.get(bitmap);
66        if (tracker.release()) {
67            recycle(tracker, bitmap);
68        }
69    }
70
71    private void recycle(InnerTracker tracker, Bitmap bitmap) {
72        if (!target.put(bitmap)) {
73            bitmap.recycle();
74        }
75        counter.remove(bitmap);
76        pool.release(tracker);
77    }
78}
79