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>
|
image gallery application.</p>
|
||||||
|
|
||||||
<p>The sample code of this class uses a {@code DiskLruCache} implementation that is pulled from the
|
<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
|
<a href="https://android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/src/main/java/libcore/io/DiskLruCache.java">Android source</a>.
|
||||||
to the existing memory cache:</p>
|
Here’s updated example code that adds a disk cache in addition to the existing memory cache:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
private DiskLruCache mDiskLruCache;
|
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
|
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
|
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
|
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>
|
<pre>
|
||||||
public static int calculateInSampleSize(
|
public static int calculateInSampleSize(
|
||||||
@@ -107,26 +108,26 @@ public static int calculateInSampleSize(
|
|||||||
final int width = options.outWidth;
|
final int width = options.outWidth;
|
||||||
int inSampleSize = 1;
|
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 halfHeight = height / 2;
|
||||||
final int heightRatio = Math.round((float) height / (float) reqHeight);
|
final int halfWidth = width / 2;
|
||||||
final int widthRatio = Math.round((float) width / (float) reqWidth);
|
|
||||||
|
|
||||||
// Choose the smallest ratio as inSampleSize value, this will guarantee
|
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
|
||||||
// a final image with both dimensions larger than or equal to the
|
// height and width larger than the requested height and width.
|
||||||
// requested height and width.
|
while ((halfHeight / inSampleSize) > reqHeight
|
||||||
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
|
&& (halfWidth / inSampleSize) > reqWidth) {
|
||||||
|
inSampleSize *= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return inSampleSize;
|
return inSampleSize;
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> Using powers of 2 for {@link
|
<p class="note"><strong>Note:</strong> A power of two value is calculated because the decoder uses
|
||||||
android.graphics.BitmapFactory.Options#inSampleSize} values is faster and more efficient for the
|
a final value by rounding down to the nearest power of two, as per the {@link
|
||||||
decoder. However, if you plan to cache the resized versions in memory or on disk, it’s usually still
|
android.graphics.BitmapFactory.Options#inSampleSize} documentation.</p>
|
||||||
worth decoding to the most appropriate image dimensions to save space.</p>
|
|
||||||
|
|
||||||
<p>To use this method, first decode with {@link
|
<p>To use this method, first decode with {@link
|
||||||
android.graphics.BitmapFactory.Options#inJustDecodeBounds} set to {@code true}, pass the options
|
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
|
which is stored in the Dalvik heap. The pixel data in native memory is
|
||||||
not released in a predictable manner, potentially causing an application
|
not released in a predictable manner, potentially causing an application
|
||||||
to briefly exceed its memory limits and crash.
|
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>
|
Dalvik heap along with the associated bitmap.</strong></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@@ -140,27 +140,16 @@ private synchronized boolean hasValidBitmap() {
|
|||||||
|
|
||||||
<h2 id="inBitmap">Manage Memory on Android 3.0 and Higher</h2>
|
<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}
|
{@link android.graphics.BitmapFactory.Options#inBitmap BitmapFactory.Options.inBitmap}
|
||||||
field. If this option is set, decode methods that take the
|
field. If this option is set, decode methods that take the
|
||||||
{@link android.graphics.BitmapFactory.Options Options} object
|
{@link android.graphics.BitmapFactory.Options Options} object
|
||||||
will attempt to reuse an existing bitmap when loading content. This means
|
will attempt to reuse an existing bitmap when loading content. This means
|
||||||
that the bitmap's memory is reused, resulting in improved performance, and
|
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
|
removing both memory allocation and de-allocation. However, there are certain restrictions with how
|
||||||
{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
|
{@link android.graphics.BitmapFactory.Options#inBitmap} can be used. In particular, before Android
|
||||||
<ul>
|
4.4 (API level 19), only equal sized bitmaps are supported. For details, please see the
|
||||||
<li>The reused bitmap must be of the same size as the source content (to make
|
{@link android.graphics.BitmapFactory.Options#inBitmap} documentation.
|
||||||
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>
|
|
||||||
|
|
||||||
<h3>Save a bitmap for later use</h3>
|
<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
|
satisfies the size criteria to be used for
|
||||||
{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
|
{@link android.graphics.BitmapFactory.Options#inBitmap}:</p>
|
||||||
|
|
||||||
<pre>private static boolean canUseForInBitmap(
|
<pre>static boolean canUseForInBitmap(
|
||||||
Bitmap candidate, BitmapFactory.Options targetOptions) {
|
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
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
// "targetOptions".
|
// From Android 4.4 (KitKat) onward we can re-use if the byte size of
|
||||||
return candidate.getWidth() == width && candidate.getHeight() == height;
|
// 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>
|
}</pre>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user