ImageViewLoader学习

来源:互联网 发布:淘宝买家v4算星级高吗 编辑:程序博客网 时间:2024/05/16 08:29
/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.imagedownloader;import android.app.ListActivity;import android.os.Bundle;import android.widget.RadioGroup;public class ImageListActivity extends ListActivity  implements RadioGroup.OnCheckedChangeListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                setContentView(R.layout.imagelist);        RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroup);        radioGroup.setOnCheckedChangeListener(this);                setListAdapter(new ImageAdapter());    }        @Override    protected void onStop() {//    ((ImageAdapter) getListAdapter()).getImageDownloader().clearCache();    super.onStop();    }    @Override    public void onCheckedChanged(RadioGroup group, int checkedId) {        ImageDownloader.Mode mode = ImageDownloader.Mode.NO_ASYNC_TASK;                if (checkedId == R.id.correctButton) {            mode = ImageDownloader.Mode.CORRECT;        }else if (checkedId == R.id.randomButton) {                mode = ImageDownloader.Mode.NO_DOWNLOADED_DRAWABLE;        }                ((ImageAdapter) getListAdapter()).getImageDownloader().setMode(mode);    }}



/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.imagedownloader;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;public class ImageAdapter extends BaseAdapter {    private static final String[] URLS = {        "http://lh5.ggpht.com/_mrb7w4gF8Ds/TCpetKSqM1I/AAAAAAAAD2c/Qef6Gsqf12Y/s144-c/_DSC4374%20copy.jpg",        "http://lh5.ggpht.com/_Z6tbBnE-swM/TB0CryLkiLI/AAAAAAAAVSo/n6B78hsDUz4/s144-c/_DSC3454.jpg",        "http://lh3.ggpht.com/_GEnSvSHk4iE/TDSfmyCfn0I/AAAAAAAAF8Y/cqmhEoxbwys/s144-c/_MG_3675.jpg",        "http://lh6.ggpht.com/_Nsxc889y6hY/TBp7jfx-cgI/AAAAAAAAHAg/Rr7jX44r2Gc/s144-c/IMGP9775a.jpg",        "http://lh3.ggpht.com/_lLj6go_T1CQ/TCD8PW09KBI/AAAAAAAAQdc/AqmOJ7eg5ig/s144-c/Juvenile%20Gannet%20despute.jpg",        "http://lh6.ggpht.com/_ZN5zQnkI67I/TCFFZaJHDnI/AAAAAAAABVk/YoUbDQHJRdo/s144-c/P9250508.JPG",        "http://lh4.ggpht.com/_XjNwVI0kmW8/TCOwNtzGheI/AAAAAAAAC84/SxFJhG7Scgo/s144-c/0014.jpg",        "http://lh6.ggpht.com/_lnDTHoDrJ_Y/TBvKsJ9qHtI/AAAAAAAAG6g/Zll2zGvrm9c/s144-c/000007.JPG",        "http://lh6.ggpht.com/_qvCl2efjxy0/TCIVI-TkuGI/AAAAAAAAOUY/vbk9MURsv48/s144-c/DSC_0844.JPG",        "http://lh4.ggpht.com/_TPlturzdSE8/TBv4ugH60PI/AAAAAAAAMsI/p2pqG85Ghhs/s144-c/_MG_3963.jpg",        "http://lh4.ggpht.com/_4f1e_yo-zMQ/TCe5h9yN-TI/AAAAAAAAXqs/8X2fIjtKjmw/s144-c/IMG_1786.JPG",        "http://lh6.ggpht.com/_iFt5VZDjxkY/TB9rQyWnJ4I/AAAAAAAADpU/lP2iStizJz0/s144-c/DSCF1014.JPG",        "http://lh5.ggpht.com/_hepKlJWopDg/TB-_WXikaYI/AAAAAAAAElI/715k4NvBM4w/s144-c/IMG_0075.JPG",        "http://lh6.ggpht.com/_OfRSx6nn68g/TCzsQic_z3I/AAAAAAABOOI/5G4Kwzb2qhk/s144-c/EASTER%20ISLAND_Hanga%20Roa_31.5.08_46.JPG",        "http://lh6.ggpht.com/_ZGv_0FWPbTE/TB-_GLhqYBI/AAAAAAABVxs/cVEvQzt0ke4/s144-c/IMG_1288_hf.jpg",        "http://lh6.ggpht.com/_a29lGRJwo0E/TBqOK_tUKmI/AAAAAAAAVbw/UloKpjsKP3c/s144-c/31012332.jpg",        "http://lh3.ggpht.com/_55Lla4_ARA4/TB6xbyxxJ9I/AAAAAAABTWo/GKe24SwECns/s144-c/Bluebird%20049.JPG",        "http://lh3.ggpht.com/_iVnqmIBYi4Y/TCaOH6rRl1I/AAAAAAAA1qg/qeMerYQ6DYo/s144-c/Kwiat_100626_0016.jpg",        "http://lh6.ggpht.com/_QFsB_q7HFlo/TCItd_2oBkI/AAAAAAAAFsk/4lgJWweJ5N8/s144-c/3705226938_d6d66d6068_o.jpg",        "http://lh5.ggpht.com/_JTI0xxNrKFA/TBsKQ9uOGNI/AAAAAAAChQg/z8Exh32VVTA/s144-c/CRW_0015-composite.jpg",        "http://lh6.ggpht.com/_loGyjar4MMI/S-InVNkTR_I/AAAAAAAADJY/Fb5ifFNGD70/s144-c/Moving%20Rock.jpg",        "http://lh4.ggpht.com/_L7i4Tra_XRY/TBtxjScXLqI/AAAAAAAAE5o/ue15HuP8eWw/s144-c/opera%20house%20II.jpg",        "http://lh3.ggpht.com/_rfAz5DWHZYs/S9cstBTv1iI/AAAAAAAAeYA/EyZPUeLMQ98/s144-c/DSC_6425.jpg",        "http://lh6.ggpht.com/_iGI-XCxGLew/S-iYQWBEG-I/AAAAAAAACB8/JuFti4elptE/s144-c/norvig-polar-bear.jpg",        "http://lh3.ggpht.com/_M3slUPpIgmk/SlbnavqG1cI/AAAAAAAACvo/z6-CnXGma7E/s144-c/mf_003.jpg",        "http://lh4.ggpht.com/_loGyjar4MMI/S-InQvd_3hI/AAAAAAAADIw/dHvCFWfyHxQ/s144-c/Rainbokeh.jpg",        "http://lh4.ggpht.com/_yy6KdedPYp4/SB5rpK3Zv0I/AAAAAAAAOM8/mokl_yo2c9E/s144-c/Point%20Reyes%20road%20.jpg",        "http://lh5.ggpht.com/_6_dLVKawGJA/SMwq86HlAqI/AAAAAAAAG5U/q1gDNkmE5hI/s144-c/mobius-glow.jpg",        "http://lh3.ggpht.com/_QFsB_q7HFlo/TCItc19Jw3I/AAAAAAAAFs4/nPfiz5VGENk/s144-c/4551649039_852be0a952_o.jpg",        "http://lh6.ggpht.com/_TQY-Nm7P7Jc/TBpjA0ks2MI/AAAAAAAABcI/J6ViH98_poM/s144-c/IMG_6517.jpg",        "http://lh3.ggpht.com/_rfAz5DWHZYs/S9cLAeKuueI/AAAAAAAAeYU/E19G8DOlJRo/s144-c/DSC_4397_8_9_tonemapped2.jpg",        "http://lh4.ggpht.com/_TQY-Nm7P7Jc/TBpi6rKfFII/AAAAAAAABbg/79FOc0Dbq0c/s144-c/david_lee_sakura.jpg",        "http://lh3.ggpht.com/_TQY-Nm7P7Jc/TBpi8EJ4eDI/AAAAAAAABb0/AZ8Cw1GCaIs/s144-c/Hokkaido%20Swans.jpg",        "http://lh3.ggpht.com/_1aZMSFkxSJI/TCIjB6od89I/AAAAAAAACHM/CLWrkH0ziII/s144-c/079.jpg",        "http://lh5.ggpht.com/_loGyjar4MMI/S-InWuHkR9I/AAAAAAAADJE/wD-XdmF7yUQ/s144-c/Colorado%20River%20Sunset.jpg",        "http://lh3.ggpht.com/_0YSlK3HfZDQ/TCExCG1Zc3I/AAAAAAAAX1w/9oCH47V6uIQ/s144-c/3138923889_a7fa89cf94_o.jpg",        "http://lh6.ggpht.com/_K29ox9DWiaM/TAXe4Fi0xTI/AAAAAAAAVIY/zZA2Qqt2HG0/s144-c/IMG_7100.JPG",        "http://lh6.ggpht.com/_0YSlK3HfZDQ/TCEx16nJqpI/AAAAAAAAX1c/R5Vkzb8l7yo/s144-c/4235400281_34d87a1e0a_o.jpg",        "http://lh4.ggpht.com/_8zSk3OGcpP4/TBsOVXXnkTI/AAAAAAAAAEo/0AwEmuqvboo/s144-c/yosemite_forrest.jpg",        "http://lh4.ggpht.com/_6_dLVKawGJA/SLZToqXXVrI/AAAAAAAAG5k/7fPSz_ldN9w/s144-c/coastal-1.jpg",        "http://lh4.ggpht.com/_WW8gsdKXVXI/TBpVr9i6BxI/AAAAAAABhNg/KC8aAJ0wVyk/s144-c/IMG_6233_1_2-2.jpg",        "http://lh3.ggpht.com/_loGyjar4MMI/S-InS0tJJSI/AAAAAAAADHU/E8GQJ_qII58/s144-c/Windmills.jpg",        "http://lh4.ggpht.com/_loGyjar4MMI/S-InbXaME3I/AAAAAAAADHo/4gNYkbxemFM/s144-c/Frantic.jpg",        "http://lh5.ggpht.com/_loGyjar4MMI/S-InKAviXzI/AAAAAAAADHA/NkyP5Gge8eQ/s144-c/Rice%20Fields.jpg",        "http://lh3.ggpht.com/_loGyjar4MMI/S-InZA8YsZI/AAAAAAAADH8/csssVxalPcc/s144-c/Seahorse.jpg",        "http://lh3.ggpht.com/_syQa1hJRWGY/TBwkCHcq6aI/AAAAAAABBEg/R5KU1WWq59E/s144-c/Antelope.JPG",        "http://lh5.ggpht.com/_MoEPoevCLZc/S9fHzNgdKDI/AAAAAAAADwE/UAno6j5StAs/s144-c/c84_7083.jpg",        "http://lh4.ggpht.com/_DJGvVWd7IEc/TBpRsGjdAyI/AAAAAAAAFNw/rdvyRDgUD8A/s144-c/Free.jpg",        "http://lh6.ggpht.com/_iO97DXC99NY/TBwq3_kmp9I/AAAAAAABcz0/apq1ffo_MZo/s144-c/IMG_0682_cp.jpg",        "http://lh4.ggpht.com/_7V85eCJY_fg/TBpXudG4_PI/AAAAAAAAPEE/8cHJ7G84TkM/s144-c/20100530_120257_0273-Edit-2.jpg"    };        private final ImageDownloader imageDownloader = new ImageDownloader();        public int getCount() {        return URLS.length;    }    public String getItem(int position) {        return URLS[position];    }    public long getItemId(int position) {        return URLS[position].hashCode();    }    public View getView(int position, View view, ViewGroup parent) {        if (view == null) {            view = new ImageView(parent.getContext());            view.setPadding(6, 6, 6, 6);        }        imageDownloader.download(URLS[position], (ImageView) view);                return view;    }    public ImageDownloader getImageDownloader() {        return imageDownloader;    }}

/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.imagedownloader;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Color;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.net.http.AndroidHttpClient;import android.os.AsyncTask;import android.os.Handler;import android.util.Log;import android.widget.ImageView;import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.concurrent.ConcurrentHashMap;/** * This helper class download images from the Internet and binds those with the provided ImageView. *  * <br>从网路下载图片并填充给指定的ImageView * * <p>It requires the INTERNET permission, which should be added to your application's manifest * file. * <br>使用该类需要在manifest配置文件中添加 INTERNET 权限。 * <p> *  * A local cache of downloaded images is maintained internally to improve performance. * <br>会维护一份本地的cache以改善性能。 */public class ImageDownloader {    private static final String LOG_TAG = "ImageDownloader";    public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }    private Mode mode = Mode.CORRECT;        /**     * Download the specified image from the Internet and binds it to the provided ImageView. The     * binding is immediate if the image is found in the cache and will be done asynchronously     * otherwise. A null bitmap will be associated to the ImageView if an error occurs.     *     * @param url The URL of the image to download.     * @param imageView The ImageView to bind the downloaded image to.     */    public void download(String url, ImageView imageView) {        resetPurgeTimer();        Bitmap bitmap = getBitmapFromCache(url);        if (bitmap == null) {            forceDownload(url, imageView);        } else {            cancelPotentialDownload(url, imageView);            imageView.setImageBitmap(bitmap);        }    }    /*     * Same as download but the image is always downloaded and the cache is not used.     * Kept private at the moment as its interest is not clear.       private void forceDownload(String url, ImageView view) {          forceDownload(url, view, null);       }     */    /**     * Same as download but the image is always downloaded and the cache is not used.     * Kept private at the moment as its interest is not clear.     */    private void forceDownload(String url, ImageView imageView) {        // State sanity: url is guaranteed to never be null in DownloadedDrawable and cache keys.        if (url == null) {            imageView.setImageDrawable(null);            return;        }        if (cancelPotentialDownload(url, imageView)) {            switch (mode) {                case NO_ASYNC_TASK:                    Bitmap bitmap = downloadBitmap(url);                    addBitmapToCache(url, bitmap);                    imageView.setImageBitmap(bitmap);                    break;                case NO_DOWNLOADED_DRAWABLE:                    imageView.setMinimumHeight(156);                    BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);                    task.execute(url);                    break;                case CORRECT:                    task = new BitmapDownloaderTask(imageView);                    DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);                    imageView.setImageDrawable(downloadedDrawable);                    imageView.setMinimumHeight(156);                    task.execute(url);                    break;            }        }    }    /**     * Returns true if the current download has been canceled or if there was no download in     * progress on this image view.     * Returns false if the download in progress deals with the same url. The download is not     * stopped in that case.     */    private static boolean cancelPotentialDownload(String url, ImageView imageView) {        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);        if (bitmapDownloaderTask != null) {            String bitmapUrl = bitmapDownloaderTask.url;            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {                bitmapDownloaderTask.cancel(true);            } else {                // The same URL is already being downloaded.                return false;            }        }        return true;    }    /**     * @param imageView Any imageView     * @return Retrieve the currently active download task (if any) associated with this imageView.     * null if there is no such task.     */    private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {        if (imageView != null) {            Drawable drawable = imageView.getDrawable();            if (drawable instanceof DownloadedDrawable) {                DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;                return downloadedDrawable.getBitmapDownloaderTask();            }        }        return null;    }    Bitmap downloadBitmap(String url) {        final int IO_BUFFER_SIZE = 4 * 1024;        // AndroidHttpClient is not allowed to be used from the main thread        final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() :            AndroidHttpClient.newInstance("Android");        final HttpGet getRequest = new HttpGet(url);        try {            HttpResponse response = client.execute(getRequest);            final int statusCode = response.getStatusLine().getStatusCode();            if (statusCode != HttpStatus.SC_OK) {                Log.w("ImageDownloader", "Error " + statusCode +                        " while retrieving bitmap from " + url);                return null;            }            final HttpEntity entity = response.getEntity();            if (entity != null) {                InputStream inputStream = null;                try {                    inputStream = entity.getContent();                    // return BitmapFactory.decodeStream(inputStream);                    // Bug on slow connections, fixed in future release.                    return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));                } finally {                    if (inputStream != null) {                        inputStream.close();                    }                    entity.consumeContent();                }            }        } catch (IOException e) {            getRequest.abort();            Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);        } catch (IllegalStateException e) {            getRequest.abort();            Log.w(LOG_TAG, "Incorrect URL: " + url);        } catch (Exception e) {            getRequest.abort();            Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);        } finally {            if ((client instanceof AndroidHttpClient)) {                ((AndroidHttpClient) client).close();            }        }        return null;    }    /*     * An InputStream that skips the exact number of bytes provided, unless it reaches EOF.     */    static class FlushedInputStream extends FilterInputStream {        public FlushedInputStream(InputStream inputStream) {            super(inputStream);        }        @Override        public long skip(long n) throws IOException {            long totalBytesSkipped = 0L;            while (totalBytesSkipped < n) {                long bytesSkipped = in.skip(n - totalBytesSkipped);                if (bytesSkipped == 0L) {                    int b = read();                    if (b < 0) {                        break;  // we reached EOF                    } else {                        bytesSkipped = 1; // we read one byte                    }                }                totalBytesSkipped += bytesSkipped;            }            return totalBytesSkipped;        }    }    /**     * The actual AsyncTask that will asynchronously download the image.     */    class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {        private String url;        private final WeakReference<ImageView> imageViewReference;        public BitmapDownloaderTask(ImageView imageView) {            imageViewReference = new WeakReference<ImageView>(imageView);        }        /**         * Actual download method.         */        @Override        protected Bitmap doInBackground(String... params) {            url = params[0];            return downloadBitmap(url);        }        /**         * Once the image is downloaded, associates it to the imageView         */        @Override        protected void onPostExecute(Bitmap bitmap) {            if (isCancelled()) {                bitmap = null;            }            addBitmapToCache(url, bitmap);            if (imageViewReference != null) {                ImageView imageView = imageViewReference.get();                BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);                // Change bitmap only if this process is still associated with it                // Or if we don't use any bitmap to task association (NO_DOWNLOADED_DRAWABLE mode)                if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) {                    imageView.setImageBitmap(bitmap);                }            }        }    }    /**     * A fake Drawable that will be attached to the imageView while the download is in progress.     *     * <p>Contains a reference to the actual download task, so that a download task can be stopped     * if a new binding is required, and makes sure that only the last started download process can     * bind its result, independently of the download finish order.</p>     */    static class DownloadedDrawable extends ColorDrawable {        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {            super(Color.BLACK);            bitmapDownloaderTaskReference =                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);        }        public BitmapDownloaderTask getBitmapDownloaderTask() {            return bitmapDownloaderTaskReference.get();        }    }    public void setMode(Mode mode) {        this.mode = mode;        clearCache();    }        /*     * Cache-related fields and methods.     *      * We use a hard and a soft cache. A soft reference cache is too aggressively cleared by the     * Garbage Collector.     */        private static final int HARD_CACHE_CAPACITY = 10;    private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds    // Hard cache, with a fixed maximum capacity and a life duration    private final HashMap<String, Bitmap> sHardBitmapCache =        new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY / 2, 0.75f, true) {        @Override        protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {            if (size() > HARD_CACHE_CAPACITY) {                // Entries push-out of hard reference cache are transferred to soft reference cache                sSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));                return true;            } else                return false;        }    };    // Soft cache for bitmaps kicked out of hard cache    private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =        new ConcurrentHashMap<String, SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2);    private final Handler purgeHandler = new Handler();    private final Runnable purger = new Runnable() {        public void run() {            clearCache();        }    };    /**     * Adds this bitmap to the cache.     * @param bitmap The newly downloaded bitmap.     */    private void addBitmapToCache(String url, Bitmap bitmap) {        if (bitmap != null) {            synchronized (sHardBitmapCache) {                sHardBitmapCache.put(url, bitmap);            }        }    }    /**     * @param url The URL of the image that will be retrieved from the cache.     * @return The cached bitmap or null if it was not found.     */    private Bitmap getBitmapFromCache(String url) {        // First try the hard reference cache        synchronized (sHardBitmapCache) {            final Bitmap bitmap = sHardBitmapCache.get(url);            if (bitmap != null) {                // Bitmap found in hard cache                // Move element to first position, so that it is removed last                sHardBitmapCache.remove(url);                sHardBitmapCache.put(url, bitmap);                return bitmap;            }        }        // Then try the soft reference cache        SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);        if (bitmapReference != null) {            final Bitmap bitmap = bitmapReference.get();            if (bitmap != null) {                // Bitmap found in soft cache                return bitmap;            } else {                // Soft reference has been Garbage Collected                sSoftBitmapCache.remove(url);            }        }        return null;    }     /**     * Clears the image cache used internally to improve performance. Note that for memory     * efficiency reasons, the cache will automatically be cleared after a certain inactivity delay.     */    public void clearCache() {        sHardBitmapCache.clear();        sSoftBitmapCache.clear();    }    /**     * Allow a new delay before the automatic cache clear is done.     */    private void resetPurgeTimer() {        purgeHandler.removeCallbacks(purger);        purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);    }}