// "Therefore those skilled at the unorthodox
// are infinite as heaven and earth,
// inexhaustible as the great rivers.
// When they come to an end,
// they begin again,
// like the days and months;
// they die and are reborn,
// like the four seasons."
//
// - Sun Tsu,
// "The Art of War"
package com.theartofdev.fastimageloader;
import android.graphics.Bitmap;
import com.theartofdev.fastimageloader.impl.util.FILLogger;
import com.theartofdev.fastimageloader.impl.util.FILUtils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Bitmap that can reuse the allocated memory to load a new image into the bitmap.
*/
public class ReusableBitmap {
//region: Fields and Consts
/**
* The actual bitmap
*/
protected Bitmap mBitmap;
/**
* the spec to load the image by
*/
protected final ImageLoadSpec mSpec;
/**
* The URL of the image loaded in the bitmap, used to know that loaded image changed
*/
protected String mBitmapUrl;
/**
* Is the bitmap is currently in use
*/
protected AtomicInteger mInUse = new AtomicInteger();
/**
* Is the bitmap is currently in use by loading, not real use
*/
protected boolean mInLoadUse;
/**
* Is the bitmap is has been released.
*/
protected boolean mClosed;
/**
* The number of times the bitmap has been recycled
*/
protected int mRecycleCount;
//endregion
/**
* @param bitmap The actual bitmap
* @param spec the spec to load the image by
*/
public ReusableBitmap(Bitmap bitmap, ImageLoadSpec spec) {
FILUtils.notNull(bitmap, "bitmap");
FILUtils.notNull(spec, "spec");
mBitmap = bitmap;
mSpec = spec;
}
/**
* The actual bitmap instance.
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
* the URI of the loaded image in the bitmap.<br>
* Used to know if the target requested image has been changed.<br>
*/
public String getUri() {
return mBitmapUrl;
}
/**
* the URL of the loaded image in the bitmap.
*/
public void setUrl(String url) {
mRecycleCount++;
mBitmapUrl = url;
}
/**
* the spec the loaded image was loaded by.
*/
public ImageLoadSpec getSpec() {
return mSpec;
}
/**
* Is the bitmap is currently in use and cannot be reused.
*/
public boolean isInUse() {
return mInUse.get() > 0 || mInLoadUse;
}
/**
* Increment the bitmap in use count by 1.<br>
* Affects the {@link #isInUse()} to know if the bitmap can be reused.<br>
* Critical to call this method correctly.
*/
public void incrementInUse() {
mInUse.incrementAndGet();
mInLoadUse = false;
}
/**
* Decrement the bitmap in use count by 1.<br>
* Affects the {@link #isInUse()} to know if the bitmap can be reused.<br>
* Critical to call this method correctly.
*/
public void decrementInUse() {
mInUse.decrementAndGet();
}
/**
* Is the bitmap is currently in use by loading, not real use.
*/
public void setInLoadUse(boolean inLoadUse) {
mInLoadUse = inLoadUse;
}
/**
* Release the inner bitmap.
*/
public void close() {
FILLogger.debug("Close recycle bitmap [{}]", this);
mClosed = true;
mBitmapUrl = null;
mBitmap.recycle();
mBitmap = null;
}
@Override
public String toString() {
return "RecycleBitmap{" +
"hash=" + hashCode() +
", mSpec='" + mSpec + '\'' +
", mInUse=" + mInUse.get() +
", mInLoadUse=" + mInLoadUse +
", mRecycleCount=" + mRecycleCount +
", mClosed=" + mClosed +
'}';
}
}