Home | History | Annotate | Download | only in engine
      1 package com.bumptech.glide.load.engine;
      2 
      3 import android.os.Looper;
      4 
      5 import com.bumptech.glide.load.Key;
      6 
      7 /**
      8  * A wrapper resource that allows reference counting a wrapped {@link com.bumptech.glide.load.engine.Resource}
      9  * interface.
     10  *
     11  * @param <Z> The type of data returned by the wrapped {@link Resource}.
     12  */
     13 class EngineResource<Z> implements Resource<Z> {
     14     private final Resource<Z> resource;
     15     private final boolean isCacheable;
     16     private ResourceListener listener;
     17     private Key key;
     18     private int acquired;
     19     private boolean isRecycled;
     20 
     21     interface ResourceListener {
     22         void onResourceReleased(Key key, EngineResource<?> resource);
     23     }
     24 
     25     EngineResource(Resource<Z> toWrap, boolean isCacheable) {
     26         if (toWrap == null) {
     27             throw new NullPointerException("Wrapped resource must not be null");
     28         }
     29         resource = toWrap;
     30         this.isCacheable = isCacheable;
     31     }
     32 
     33     void setResourceListener(Key key, ResourceListener listener) {
     34         this.key = key;
     35         this.listener = listener;
     36     }
     37 
     38     boolean isCacheable() {
     39         return isCacheable;
     40     }
     41 
     42     @Override
     43     public Z get() {
     44         return resource.get();
     45     }
     46 
     47     @Override
     48     public int getSize() {
     49         return resource.getSize();
     50     }
     51 
     52     @Override
     53     public void recycle() {
     54         if (acquired > 0) {
     55             throw new IllegalStateException("Cannot recycle a resource while it is still acquired");
     56         }
     57         if (isRecycled) {
     58             throw new IllegalStateException("Cannot recycle a resource that has already been recycled");
     59         }
     60         isRecycled = true;
     61         resource.recycle();
     62     }
     63 
     64     /**
     65      * Increments the number of consumers using the wrapped resource. Must be called on the main thread.
     66      *
     67      * <p>
     68      *     This must be called with a number corresponding to the number of new consumers each time new consumers
     69      *     begin using the wrapped resource. It is always safer to call acquire more often than necessary. Generally
     70      *     external users should never call this method, the framework will take care of this for you.
     71      * </p>
     72      */
     73     void acquire() {
     74         if (isRecycled) {
     75             throw new IllegalStateException("Cannot acquire a recycled resource");
     76         }
     77         if (!Looper.getMainLooper().equals(Looper.myLooper())) {
     78             throw new IllegalThreadStateException("Must call acquire on the main thread");
     79         }
     80         ++acquired;
     81     }
     82 
     83     /**
     84      * Decrements the number of consumers using the wrapped resource. Must be called on the main thread.
     85      *
     86      * <p>
     87      *     This must only be called when a consumer that called the {@link #acquire()} method is now done with the
     88      *     resource. Generally external users should never callthis method, the framework will take care of this for
     89      *     you.
     90      * </p>
     91      */
     92     void release() {
     93         if (acquired <= 0) {
     94             throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
     95         }
     96         if (!Looper.getMainLooper().equals(Looper.myLooper())) {
     97             throw new IllegalThreadStateException("Must call release on the main thread");
     98         }
     99         if (--acquired == 0) {
    100             listener.onResourceReleased(key, this);
    101         }
    102     }
    103 }
    104