am 7fd5c53c: Merge "Displaying Bitmaps Efficiently Training - updates for KitKat inBitmap changes Bug: 10411797" into klp-dev
* commit '7fd5c53c4507995da1e1f1300a2f9def30bffce8': Displaying Bitmaps Efficiently Training - updates for KitKat inBitmap changes Bug: 10411797
This commit is contained in:
Binary file not shown.
@@ -188,8 +188,8 @@ appropriate place to store cached images if they are accessed more frequently, f
|
||||
image gallery application.</p>
|
||||
|
||||
<p>The sample code of this class uses a {@code DiskLruCache} implementation that is pulled from the
|
||||
<a href="https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/libcore/io/DiskLruCache.java">Android source</a>. Here’s updated example code that adds a disk cache in addition
|
||||
to the existing memory cache:</p>
|
||||
<a href="https://android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/src/main/java/libcore/io/DiskLruCache.java">Android source</a>.
|
||||
Here’s updated example code that adds a disk cache in addition to the existing memory cache:</p>
|
||||
|
||||
<pre>
|
||||
private DiskLruCache mDiskLruCache;
|
||||
|
||||
@@ -97,7 +97,8 @@ android.graphics.BitmapFactory.Options} object. For example, an image with resol
|
||||
is decoded with an {@link android.graphics.BitmapFactory.Options#inSampleSize} of 4 produces a
|
||||
bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full
|
||||
image (assuming a bitmap configuration of {@link android.graphics.Bitmap.Config ARGB_8888}). Here’s
|
||||
a method to calculate a the sample size value based on a target width and height:</p>
|
||||
a method to calculate a sample size value that is a power of two based on a target width and
|
||||
height:</p>
|
||||
|
||||
<pre>
|
||||
public static int calculateInSampleSize(
|
||||
@@ -107,26 +108,26 @@ public static int calculateInSampleSize(
|
||||
final int width = options.outWidth;
|
||||
int inSampleSize = 1;
|
||||
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
|
||||
// Calculate ratios of height and width to requested height and width
|
||||
final int heightRatio = Math.round((float) height / (float) reqHeight);
|
||||
final int widthRatio = Math.round((float) width / (float) reqWidth);
|
||||
final int halfHeight = height / 2;
|
||||
final int halfWidth = width / 2;
|
||||
|
||||
// Choose the smallest ratio as inSampleSize value, this will guarantee
|
||||
// a final image with both dimensions larger than or equal to the
|
||||
// requested height and width.
|
||||
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
|
||||
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
||||
// height and width larger than the requested height and width.
|
||||
while ((halfHeight / inSampleSize) > reqHeight
|
||||
&& (halfWidth / inSampleSize) > reqWidth) {
|
||||
inSampleSize *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return inSampleSize;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Using powers of 2 for {@link
|
||||
android.graphics.BitmapFactory.Options#inSampleSize} values is faster and more efficient for the
|
||||
decoder. However, if you plan to cache the resized versions in memory or on disk, it’s usually still
|
||||
worth decoding to the most appropriate image dimensions to save space.</p>
|
||||
<p class="note"><strong>Note:</strong> A power of two value is calculated because the decoder uses
|
||||
a final value by rounding down to the nearest power of two, as per the {@link
|
||||
android.graphics.BitmapFactory.Options#inSampleSize} documentation.</p>
|
||||
|
||||
<p>To use this method, first decode with {@link
|
||||
android.graphics.BitmapFactory.Options#inJustDecodeBounds} set to {@code true}, pass the options
|
||||
|
||||
@@ -56,7 +56,7 @@ bitmap is stored in native memory. It is separate from the bitmap itself,
|
||||
which is stored in the Dalvik heap. The pixel data in native memory is
|
||||
not released in a predictable manner, potentially causing an application
|
||||
to briefly exceed its memory limits and crash.
|
||||
<strong>As of Android 3.0 (API Level 11), the pixel data is stored on the
|
||||
<strong>As of Android 3.0 (API level 11), the pixel data is stored on the
|
||||
Dalvik heap along with the associated bitmap.</strong></li>
|
||||
|
||||
</ul>
|
||||
@@ -140,27 +140,16 @@ private synchronized boolean hasValidBitmap() {
|
||||
|
||||
<h2 id="inBitmap">Manage Memory on Android 3.0 and Higher</h2>
|
||||
|
||||
<p>Android 3.0 (API Level 11) introduces the
|
||||
<p>Android 3.0 (API level 11) introduces the
|
||||
{@link android.graphics.BitmapFactory.Options#inBitmap BitmapFactory.Options.inBitmap}
|
||||
field. If this option is set, decode methods that take the
|
||||
{@link android.graphics.BitmapFactory.Options Options} object
|
||||
will attempt to reuse an existing bitmap when loading content. This means
|
||||
that the bitmap's memory is reused, resulting in improved performance, and
|
||||
removing both memory allocation and de-allocation. There are some caveats in using
|
||||
{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
|
||||
<ul>
|
||||
<li>The reused bitmap must be of the same size as the source content (to make
|
||||
sure that the same amount of memory is used), and in JPEG or PNG format
|
||||
(whether as a resource or as a stream).</li>
|
||||
|
||||
|
||||
<li>The {@link android.graphics.Bitmap.Config configuration} of the reused bitmap
|
||||
overrides the setting of
|
||||
{@link android.graphics.BitmapFactory.Options#inPreferredConfig}, if set. </li>
|
||||
|
||||
<li>You should always use the returned bitmap of the decode method,
|
||||
because you can't assume that reusing the bitmap worked (for example, if there is
|
||||
a size mismatch).</li>
|
||||
removing both memory allocation and de-allocation. However, there are certain restrictions with how
|
||||
{@link android.graphics.BitmapFactory.Options#inBitmap} can be used. In particular, before Android
|
||||
4.4 (API level 19), only equal sized bitmaps are supported. For details, please see the
|
||||
{@link android.graphics.BitmapFactory.Options#inBitmap} documentation.
|
||||
|
||||
<h3>Save a bitmap for later use</h3>
|
||||
|
||||
@@ -283,14 +272,39 @@ protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
|
||||
satisfies the size criteria to be used for
|
||||
{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
|
||||
|
||||
<pre>private static boolean canUseForInBitmap(
|
||||
<pre>static boolean canUseForInBitmap(
|
||||
Bitmap candidate, BitmapFactory.Options targetOptions) {
|
||||
int width = targetOptions.outWidth / targetOptions.inSampleSize;
|
||||
int height = targetOptions.outHeight / targetOptions.inSampleSize;
|
||||
|
||||
// Returns true if "candidate" can be used for inBitmap re-use with
|
||||
// "targetOptions".
|
||||
return candidate.getWidth() == width && candidate.getHeight() == height;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// From Android 4.4 (KitKat) onward we can re-use if the byte size of
|
||||
// the new bitmap is smaller than the reusable bitmap candidate
|
||||
// allocation byte count.
|
||||
int width = targetOptions.outWidth / targetOptions.inSampleSize;
|
||||
int height = targetOptions.outHeight / targetOptions.inSampleSize;
|
||||
int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
|
||||
return byteCount <= candidate.getAllocationByteCount();
|
||||
}
|
||||
|
||||
// On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
|
||||
return candidate.getWidth() == targetOptions.outWidth
|
||||
&& candidate.getHeight() == targetOptions.outHeight
|
||||
&& targetOptions.inSampleSize == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to return the byte usage per pixel of a bitmap based on its configuration.
|
||||
*/
|
||||
static int getBytesPerPixel(Config config) {
|
||||
if (config == Config.ARGB_8888) {
|
||||
return 4;
|
||||
} else if (config == Config.RGB_565) {
|
||||
return 2;
|
||||
} else if (config == Config.ARGB_4444) {
|
||||
return 2;
|
||||
} else if (config == Config.ALPHA_8) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}</pre>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user