废话就不多说了,开始。。。

转载请表明出处:http://blog.csdn.net/android_ls/article/details/8797740

明声:常有人说,能把杂复的情事,用最简略艰深式方向大家描述清晰,此乃“牛人”或称“师大别级”。我自知离那个别级还差很远。因此,我宣布的仿人人Android客户端系列博文,是与有定一Andoird基础知识的友人来分享的。

这篇是基于上一篇Android仿人人客户端(v5.7.1)——对从服务器端(络网)得获的图片行进地本双缓存理处(流程图或活动图)来行进讲授,没看过的可以先浏览下上一篇博文,其实我个人得觉图片双缓存理处这块,一张流程图已足以明说一切。至于码编现实,不同的人有不同的现实式方,面下我就和大家聊一聊我的现实式方:

一、图片双缓存理处,类图如下:

二、络网图片地本双缓存的码编现实(以得获户用图像为例):

1、出发要需表现户用图像的请求

String headUrl = user.getHeadurl();                        LogUtil.i(TAG, "headUrl = " + user.getHeadurl());                                               // 户用图像的巨细48x48,单位为dip,转换为px                        int widthPx = DensityUtil.dip2px(mContext, 48);                                                // 要一张角圆高量质的图片                        ImageInfo imgInfo = new ImageInfo(mLeftPanelLayout.ivUserIcon, headUrl, widthPx, widthPx, true, false);                        mImageLoader.displayImage(imgInfo);

注:mLeftPanelLayout.ivUserIcon为ImageView;ImageInfo对象封装了图片请求参数。

2、根据URL从存内缓存中得获Bitmap对象,找到了Bitmap对象,用ImageView对象表现图像,到这里止终。

Bitmap bitmap = memoryCache.get(url);        if (bitmap != null) {            imageView.setImageBitmap(bitmap);        }

注:memoryCache是MemoryCache(存内缓存类)的对象引用。

3 、没有从缓存中找到了Bitmap对象,则根据URL从文件缓存中得获File对象,将File对象解码(剖析)成Bitmap对象,用ImageView对象表现户用图像,到这里止终。

final File file = fileCache.getFile(url);            if(file.exists()){                String pathName = file.getAbsolutePath();                System.out.println("pathName = " + pathName);                System.out.println("file.length() = " + file.length());                                bitmap = BitmapFactory.decodeFile(pathName);                imageView.setImageBitmap(bitmap);            }

注:fileCache为文件缓存类的引用

4、没有从文件缓存中找到File对象,则开启络网请求务业线程。

// 开启线程加载图片                try {                    AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {                        @Override                        public void onSuccess(Object obj) {                                                    }                        @Override                        public void onFail(int errorCode) {                            System.out.println("Loading image error. errorCode = " + errorCode);                        }                    });                    mDefaultThreadPool.execute(asyncRequest);                    mAsyncRequests.add(asyncRequest);                } catch (IOException e) {                    e.printStackTrace();                }

5、络网请求返回的图片数据流可能会很大,直接解码成生Bitmap对象,可能会形成OOM。因此,要根据指定的缩压比例,得获适合的Bitmap

Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight());

6、上一步理处后过,可能解码成生的Bitmap对象还会很大,可能还会形成OOM,因此,Bitmap对象再次行进量质缩压。

if (imgInfo.isCompress()) {                                    // 对Bitmap行进量质缩压                                    bitmap = BitmapUtil.compressBitmap(bitmap);                                }

7、行进地本文件缓存

try {                                fileCache.writeToFile(inStream, file);                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }

8、行进地本存内缓存

// 将数据流将其转换成Bitmap                            bitmap = BitmapFactory.decodeStream(inStream);                            // 存入存内缓存中                            memoryCache.put(url, bitmap);

9、用ImageView对象表现户用图像,到这里止终。

// 用ImageView对象表现图片                            final Bitmap btm = bitmap;                            mHandler.post(new Runnable() {                                @Override                                public void run() {                                    imageView.setImageBitmap(btm);                                }                            });

加载图片的整完方法,码代如下:

/**     * 加载图片     * @param imgInfo 图片信息     */    public void displayImage(final ImageInfo imgInfo) {        final ImageView imageView = imgInfo.getImageView();        final String url = imgInfo.getUrl();        imageViews.put(imageView, url);        // 从存内缓存中找查        Bitmap bitmap = memoryCache.get(url);        if (bitmap != null) {            imageView.setImageBitmap(bitmap);        } else {            // 从文件缓存中找查            final File file = fileCache.getFile(url);            if (file.exists()) {                String pathName = file.getAbsolutePath();                System.out.println("pathName = " + pathName);                System.out.println("file.length() = " + file.length());                bitmap = BitmapFactory.decodeFile(pathName);                imageView.setImageBitmap(bitmap);            } else {                // 开启线程加载图片                try {                    AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {                        @Override                        public void onSuccess(Object obj) {                            if (obj == null || !(obj instanceof InputStream)) {                                System.out.println("Loading image return Object is null or not is InputStream.");                                return;                            }                            try {                                // 根据指定的缩压比例,得获适合的Bitmap                                Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight());                                                                if (imgInfo.isRounded()) {                                     // 将图片酿成角圆                                     // bitmap = BitmapUtil.drawRoundCorner(bitmap, 8);                                     bitmap = BitmapUtil.drawRoundBitmap(bitmap, 8);                                }                                                                if (imgInfo.isCompress()) {                                    // 对Bitmap行进量质缩压                                    bitmap = BitmapUtil.compressBitmap(bitmap);                                }                                                                // 将Bitmap转换成ByteArrayInputStream                                ByteArrayOutputStream outStream = new ByteArrayOutputStream();                                bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);                                ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());                                                                // 将行进量质缩压后的数据写入文件(文件缓存)                                fileCache.writeToFile(inStream, file);                                                                // 存入存内缓存中                                memoryCache.put(url, bitmap);                                // 止防图片错位                                String tag = imageViews.get(imageView);                                if (tag == null || !tag.equals(url)) {                                    System.out.println("tag is null or url and ImageView disaccord.");                                    return;                                }                                                                // 用ImageView对象表现图片                                final Bitmap btm = bitmap;                                mHandler.post(new Runnable() {                                    @Override                                    public void run() {                                        imageView.setImageBitmap(btm);                                    }                                });                                                                                            } catch (IOException e) {                                // 这里不做理处,因为默许表现的图片在xml组件配置里已设置                                e.printStackTrace();                            }                                                    }                        @Override                        public void onFail(int errorCode) {                            System.out.println("Loading image error. errorCode = " + errorCode);                        }                    });                    mDefaultThreadPool.execute(asyncRequest);                    mAsyncRequests.add(asyncRequest);                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }

三、在上述务业理处中程过,碰到的问题及处理思绪(记载理处进程)

1、根据指定的缩压比例,得获适合的Bitmap,浏览如下码代:

/**     * 根据指定的缩压比例,得获适合的Bitmap     * @param inStream InputStream     * @param width 指定的宽度     * @param height 指定的度高     */    public static Bitmap decodeStream(InputStream inStream, int width, int height) {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeStream(inStream, null, options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeStream(inStream, null, options);    }

注:inStream为从络网得获后,直接传进来的。

行运面下的后,返回的Bitmap对象为null。究其原因,在设置options.inJustDecodeBounds = true后,我们调用了BitmapFactory.decodeStream(inStream, null, options)方法得获图片的巨细,但是该方法在执行完后,该应在内部把传进去的InputStream关闭掉了。第二次的时候就读不到数据了。处理思绪,将从络网得获到的数据流先存保起来。处理方法一:

/**     * 根据指定的缩压比例,得获适合的Bitmap(方法一)     * @param file File     * @param width 指定的宽度     * @param height 指定的度高     * @return Bitmap     */    public static Bitmap decodeStream(File file, int width, int height) {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeFile(file.getAbsolutePath(), options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options = new BitmapFactory.Options();        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeFile(file.getAbsolutePath(), options);    }

处理方法二:

/**     * 根据指定的缩压比例,得获适合的Bitmap(方法二)     * @param inStream InputStream     * @param width 指定的宽度     * @param height 指定的度高     * @return Bitmap     * @throws IOException     */    public static Bitmap decodeStream(InputStream inStream, int width, int height) throws IOException {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        // 从输入流读取数据        byte[] data = StreamTool.read(inStream);        BitmapFactory.decodeByteArray(data, 0, data.length, options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeByteArray(data, 0, data.length);    }

处理方法三:从络网返回的数据流中只读取图片的信息(宽度和度高),盘算缩压比例,后之再次从络网读取数据按第一次盘算出的缩压比例,得获适合的Bitmap。(这个是下下策,要问访两次络网)

2、对Bitmap行进量质缩压,浏览如下码代:

/**     * 对Bitmap行进量质缩压     * @param bitmap Bitmap     * @return ByteArrayInputStream     */    public static Bitmap compressBitmap(Bitmap bitmap) {        ByteArrayOutputStream outStream = new ByteArrayOutputStream();        // 图片量质默许值为100,表示不缩压        int quality = 100;        // PNG是无损的,将会略忽量质设置。因此,这里设置为JPEG        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);        // 判断缩压后图片的巨细否是大于100KB,大于则继承缩压        while (outStream.toByteArray().length / 1024 > 100) {            outStream.reset();            // 缩压quality%,把缩压后的数据寄存到baos中            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);            quality -= 10;        }        System.out.println("quality = " + quality);        byte[] data = outStream.toByteArray();        return BitmapFactory.decodeByteArray(data, 0, data.length);    }

注意: bitmap.compress(Bitmap.CompressFormat.PNG, quality, outStream);如果这么写,是没有缩压效果的。因为PNG是无损的,将会略忽量质设置。

四、上述讲授中涉及到的类,整完的源文件如下:

加载(装载)图片类

package com.everyone.android.bitmap;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.text.SimpleDateFormat;import java.util.Collections;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.widget.ImageView;import com.everyone.android.AppBaseActivity;import com.everyone.android.callback.ResultCallback;import com.everyone.android.entity.ImageInfo;import com.everyone.android.net.AsyncBaseRequest;import com.everyone.android.net.AsyncHttpGet;import com.everyone.android.net.DefaultThreadPool;import com.everyone.android.utils.BitmapUtil;/** * 能功描述:加载(装载)图片 *  * 在前以,一个非常行流的存内缓存的现实是用使SoftReference or WeakReference ,但是种这方法当初其实不荐推。 * 从Android 2.3开始,垃圾收回器会更加踊跃的去收回软引用和弱引用引用的对象,这样致导种这做法相称的无效。 * 另外,在Android 3.0之前,图片数据存保在地本存内中,它们不是以一种可见预的式方来放释的, * 这样可能会致导用应存内的消耗量现出暂短的超限,用应程序溃崩 。 *  * @author android_ls */public class ImageLoader {    /**     * 存内缓存     */    private MemoryCache memoryCache;    /**     * 文件缓存     */    private FileCache fileCache;    /**     * 寄存图片的表现视图ImageView和图片的URL     */    private Map<ImageView, String> imageViews = Collections.synchronizedMap(new LinkedHashMap<ImageView, String>());    private List<AsyncBaseRequest> mAsyncRequests;    private DefaultThreadPool mDefaultThreadPool;    private Handler mHandler;    public ImageLoader(AppBaseActivity activity) {        this.memoryCache = new MemoryCache();        this.fileCache = new FileCache(activity.getContext());        this.mAsyncRequests = activity.getAsyncRequests();        this.mDefaultThreadPool = activity.getDefaultThreadPool();        this.mHandler = activity.getHandler();    }    /**     * 加载图片     * @param imgInfo 图片信息     */    public void displayImage(final ImageInfo imgInfo) {        final ImageView imageView = imgInfo.getImageView();        final String url = imgInfo.getUrl();        imageViews.put(imageView, url);        // 从存内缓存中找查        Bitmap bitmap = memoryCache.get(url);        if (bitmap != null) {            imageView.setImageBitmap(bitmap);        } else {            // 从文件缓存中找查            final File file = fileCache.getFile(url);            if (file.exists()) {                String pathName = file.getAbsolutePath();                System.out.println("pathName = " + pathName);                System.out.println("file.length() = " + file.length());                SimpleDateFormat mDateFormat = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss");                System.out.println("file.lastModified() = " + mDateFormat.format(file.lastModified()));                                bitmap = BitmapFactory.decodeFile(pathName);                imageView.setImageBitmap(bitmap);            } else {                // 开启线程加载图片                try {                    AsyncBaseRequest asyncRequest = new AsyncHttpGet(url, null, null, new ResultCallback() {                        @Override                        public void onSuccess(Object obj) {                            if (obj == null || !(obj instanceof InputStream)) {                                System.out.println("Loading image return Object is null or not is InputStream.");                                return;                            }                            try {                                // 根据指定的缩压比例,得获适合的Bitmap                                Bitmap bitmap = BitmapUtil.decodeStream((InputStream) obj, imgInfo.getWidth(), imgInfo.getHeight());                                                                if (imgInfo.isRounded()) {                                     // 将图片酿成角圆                                     // bitmap = BitmapUtil.drawRoundCorner(bitmap, 8);                                     bitmap = BitmapUtil.drawRoundBitmap(bitmap, 8);                                }                                                                if (imgInfo.isCompress()) {                                    // 对Bitmap行进量质缩压                                    bitmap = BitmapUtil.compressBitmap(bitmap);                                }                                                                // 将Bitmap转换成ByteArrayInputStream                                ByteArrayOutputStream outStream = new ByteArrayOutputStream();                                bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);                                ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());                                                                // 将行进量质缩压后的数据写入文件(文件缓存)                                fileCache.writeToFile(inStream, file);                                                                // 存入存内缓存中                                memoryCache.put(url, bitmap);                                // 止防图片错位                                String tag = imageViews.get(imageView);                                if (tag == null || !tag.equals(url)) {                                    System.out.println("tag is null or url and ImageView disaccord.");                                    return;                                }                                                                // 用ImageView对象表现图片                                final Bitmap btm = bitmap;                                mHandler.post(new Runnable() {                                    @Override                                    public void run() {                                        imageView.setImageBitmap(btm);                                    }                                });                                                                                            } catch (IOException e) {                                // 这里不做理处,因为默许表现的图片在xml组件配置里已设置                                e.printStackTrace();                            }                                                    }                        @Override                        public void onFail(int errorCode) {                            System.out.println("Loading image error. errorCode = " + errorCode);                        }                    });                    mDefaultThreadPool.execute(asyncRequest);                    mAsyncRequests.add(asyncRequest);                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}


存内缓存类

package com.everyone.android.bitmap;import java.util.Collections;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Map;import java.util.Map.Entry;import android.graphics.Bitmap;import android.util.Log;/** * 能功描述:存内缓存类 *  * @author android_ls */public class MemoryCache {    /**     * 打印LOG的TAG     */    private static final String TAG = "MemoryCache";    /**     * 放入缓存时是个同步操作     * LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最近用使次数由少到多排列,     * 这样的利益是如果要将缓存中的元素替换,则先遍历出最近最少用使的元来素替换以进步率效     */    private Map<String, Bitmap> cacheMap = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));    // 缓存只能占用的最大堆存内    private long maxMemory;    public MemoryCache() {        // 用使25%的可用的堆巨细        maxMemory = Runtime.getRuntime().maxMemory() / 4;        Log.i(TAG, "MemoryCache will use up to " + (maxMemory / 1024 / 1024) + "MB");    }    /**     * 根据key得获响应的图片     * @param key     * @return Bitmap     */    public Bitmap get(String key) {        if (!cacheMap.containsKey(key)){            return null;        }        return cacheMap.get(key);    }    /**     * 添加图片到缓存     * @param key     * @param bitmap     */    public synchronized void put(String key, Bitmap bitmap) {        checkSize();        cacheMap.put(key, bitmap);               Log.i(TAG, "cache size=" + cacheMap.size() + " bitmap size = " +  getBitmapSize(bitmap));    }    /**     * 严格控制堆存内,如果过超将首先替换最近最少用使的那个图片缓存     */    private void checkSize() {        long count = 0;        Iterator<Entry<String, Bitmap>> iterator = cacheMap.entrySet().iterator();        while (iterator.hasNext()) {            Entry<String, Bitmap> entry = iterator.next();            count += getBitmapSize(entry.getValue());        }        Log.i(TAG, "cache size=" + count + " length=" + cacheMap.size());        if (count > maxMemory) {            while (iterator.hasNext()) {                Entry<String, Bitmap> entry = iterator.next();                count -= getBitmapSize(entry.getValue());                iterator.remove();                if (count <= maxMemory) {                    System.out.println("够用了,不用在删除了");                    break;                }            }            Log.i(TAG, "Clean cache. New size " + cacheMap.size());        }    }    /**     * 得获bitmap的字节巨细     * @param bitmap     * @return     */    private long getBitmapSize(Bitmap bitmap) {        if (bitmap == null) {            return 0;        }        return bitmap.getRowBytes() * bitmap.getHeight();    }    /**     * 空清缓存     */    public void clear() {        cacheMap.clear();    }}

络网下载文件地本缓存类

package com.everyone.android.bitmap;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.text.SimpleDateFormat;import java.util.Arrays;import java.util.Comparator;import android.content.Context;import android.os.StatFs;/** * 能功描述:络网下载文件地本缓存类 *  * @author android_ls */public class FileCache {    /**     * 地本与我们用应程序关相文件寄存的根目录     */    private static final String ROOT_DIR_PATH = "CopyEveryone";    /**     * 下载文件寄存的目录     */    private static final String IMAGE_DOWNLOAD_CACHE_PATH = ROOT_DIR_PATH + "/Download/cache";    /**     * 默许的盘磁缓存巨细(20MB)     */    private static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 20;    /**     * 缓存文件寄存目录     */    private File cacheDir;    /**     * 缓存根目录     */    private String cacheRootDir;        private Context mContext;    public FileCache(Context context) {        mContext = context;                if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {            cacheRootDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();        } else {            cacheRootDir = mContext.getCacheDir().getAbsolutePath();        }        cacheDir = new File(cacheRootDir + File.separator + IMAGE_DOWNLOAD_CACHE_PATH);        // 检测文件缓存目录否是存在,不存在则创立        if (!cacheDir.exists()) {            cacheDir.mkdirs();        }    }    /**     * 得获下载的文件要寄存的缓存目录     * /mnt/sdcard/CopyEveryone/Download/cache     * @return 缓存目录的全路径     */    public String getCacheDirPath() {        return cacheDir.getAbsolutePath();    }    /**     * 根据URL从文件缓存中得获文件     * @param url url的hashCode为缓存的文件名     */    public File getFile(String url) {        if (!cacheDir.exists()) {            cacheDir.mkdirs();        }        String filename = String.valueOf(url.hashCode());        File file = new File(cacheDir, filename);        return file;    }    /**     * 盘算存储可用的巨细     * @return     */    public long getAvailableMemorySize() {        StatFs stat = new StatFs(cacheRootDir);        long blockSize = stat.getBlockSize();        long availableBlocks = stat.getAvailableBlocks();        return availableBlocks * blockSize;    }    /**     * 将指定的数据写入文件     * @param inputStream InputStream     * @param outputStream OutputStream     * @throws IOException      */    public synchronized void writeToFile(InputStream inputStream, File file) throws IOException {        int fileSize  = inputStream.available();        System.out.println("fileSize = " + fileSize);                long enabledMemory  = getAvailableMemorySize();        System.out.println("前当可用盘硬: " + (enabledMemory/1024/1024)); // 单位:MB                // 前当可用存储空间缺乏20M        if(DEFAULT_DISK_CACHE_SIZE > enabledMemory){            if (fileSize > enabledMemory) {                // 检测可用空间巨细,若不够用则删除最早的文件                File[] files = cacheDir.listFiles();                Arrays.sort(files, new FileLastModifSort());                                int length = files.length;                for (int i = 0; i < length; i++) {                    files[i].delete();                    length = files.length;                                        enabledMemory  = getAvailableMemorySize();                    System.out.println("前当可用存内: " + enabledMemory);                                        if (fileSize <= enabledMemory) {                        System.out.println("够用了,不用在删除了");                        break;                    }                }            }        } else {            int count = 0;            File[] files = cacheDir.listFiles();            for (int i = 0; i < files.length; i++) {                count += files[i].length();            }                        System.out.println("file cache size = " + count);                        // 用使的空间大于下限            enabledMemory = DEFAULT_DISK_CACHE_SIZE - count;            if(fileSize > enabledMemory){                Arrays.sort(files, new FileLastModifSort());                                int length = files.length;                for (int i = 0; i < length; i++) {                    count -= files[i].length();                    files[i].delete();                    length = files.length;                                       enabledMemory = DEFAULT_DISK_CACHE_SIZE - count;                    if (fileSize <= enabledMemory) {                        System.out.println("够用了,不用在删除了");                        break;                    }                }            }        }                if(enabledMemory == 0){            return;        }                // 将数据写入文件存保        FileOutputStream outStream = new FileOutputStream(file);        byte[] buffer = new byte[1024];        int len = 0;        while ((len = inputStream.read(buffer)) != -1) {            outStream.write(buffer, 0, len);        }        outStream.flush();        outStream.close();        inputStream.close();                // 设置最后改修的间时        long newModifiedTime = System.currentTimeMillis();        file.setLastModified(newModifiedTime);                System.out.println("file.length() = " + file.length());                SimpleDateFormat mDateFormat = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss");        System.out.println("writeToFile file.lastModified() = " + mDateFormat.format(file.lastModified()));    }   /**    * 根据文件的最后改修间时行进排序    * @author android_ls    *    */    class FileLastModifSort implements Comparator<File> {        public int compare(File file1, File file2) {            if (file1.lastModified() > file2.lastModified()) {                return 1;            } else if (file1.lastModified() == file2.lastModified()) {                return 0;            } else {                return -1;            }        }    }    /**     * 空清缓存的文件     */    public void clear() {        if (!cacheDir.exists()) {            return;        }        File[] files = cacheDir.listFiles();        if (files != null) {            for (File f : files) {                f.delete();            }        }    }}

图片信息实体类

package com.everyone.android.entity;import android.widget.ImageView;/** * 能功描述:图片信息实体类 *  * @author android_ls */public class ImageInfo {    private int id; // 独一标识    private ImageView imageView; // 用于表现的组件    private String url; // 络网URL    private int width; // 宽度    private int height; // 度高    private boolean rounded; // 否是要转换成角圆    private boolean compress; // 否是要行进量质缩压    public ImageInfo(ImageView imageView, String url) {        this.imageView = imageView;        this.url = url;    }    public ImageInfo() {    }    public ImageInfo(ImageView imageView, String url, int width, int height, boolean rounded, boolean compress) {        this.imageView = imageView;        this.url = url;        this.width = width;        this.height = height;        this.rounded = rounded;        this.compress = compress;    }    public ImageInfo(ImageView imageView, String url, boolean rounded) {        this.imageView = imageView;        this.url = url;        this.rounded = rounded;    }    public ImageInfo(ImageView imageView, String url, int width, int height) {        this.imageView = imageView;        this.url = url;        this.width = width;        this.height = height;    }    public ImageInfo(ImageView imageView, String url, int width, int height, boolean rounded) {        this.imageView = imageView;        this.url = url;        this.width = width;        this.height = height;        this.rounded = rounded;    }    public boolean isCompress() {        return compress;    }    public void setCompress(boolean compress) {        this.compress = compress;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public ImageView getImageView() {        return imageView;    }    public void setImageView(ImageView imageView) {        this.imageView = imageView;    }    public String getUrl() {        return url;    }    public void setUrl(String url) {        this.url = url;    }    public int getWidth() {        return width;    }    public void setWidth(int width) {        this.width = width;    }    public int getHeight() {        return height;    }    public void setHeight(int height) {        this.height = height;    }    public boolean isRounded() {        return rounded;    }    public void setRounded(boolean rounded) {        this.rounded = rounded;    }}

Bitmap加工理处具工类

package com.everyone.android.utils;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuff.Mode;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;/** * 能功描述:Bitmap加工理处具工类 * @author android_ls * */public class BitmapUtil {    /**     * 将图片酿成角圆(方法一)     * @param bitmap Bitmap     * @param pixels 角圆的弧度     * @return 角圆图片     */    public static Bitmap drawRoundBitmap(Bitmap bitmap, float pixels) {        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);        Canvas canvas = new Canvas(output);        final Paint paint = new Paint();        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());        final RectF rectF = new RectF(rect);        paint.setAntiAlias(true);        canvas.drawARGB(0, 0, 0, 0);        // paint.setColor()的参数,除不能为Color.TRANSPARENT外,可以意任写        paint.setColor(Color.RED);        canvas.drawRoundRect(rectF, pixels, pixels, paint);        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));        canvas.drawBitmap(bitmap, rect, rect, paint);        return output;    }    /**     * 将图片酿成角圆(方法二)     * @param bitmap Bitmap     * @param pixels 角圆的弧度     * @return 角圆图片     */    public static Bitmap drawRoundCorner(Bitmap bitmap, float pixels) {        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);        Canvas canvas = new Canvas(output);        RectF outerRect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);        // paint.setColor()的参数,除不能为Color.TRANSPARENT外,可以意任写        paint.setColor(Color.WHITE);        canvas.drawRoundRect(outerRect, pixels, pixels, paint);        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        Drawable drawable = new BitmapDrawable(bitmap);        drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());        canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG);        drawable.draw(canvas);        canvas.restore();        return output;    }    /**     * 对Bitmap行进量质缩压     * @param bitmap Bitmap     * @return ByteArrayInputStream     */    public static Bitmap compressBitmap(Bitmap bitmap) {        ByteArrayOutputStream outStream = new ByteArrayOutputStream();        // 图片量质默许值为100,表示不缩压        int quality = 100;        // PNG是无损的,将会略忽量质设置。因此,这里设置为JPEG        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);        // 判断缩压后图片的巨细否是大于100KB,大于则继承缩压        while (outStream.toByteArray().length / 1024 > 100) {            outStream.reset();            // 缩压quality%,把缩压后的数据寄存到baos中            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);            quality -= 10;        }        System.out.println("quality = " + quality);        byte[] data = outStream.toByteArray();        return BitmapFactory.decodeByteArray(data, 0, data.length);    }    /**     * 根据指定的缩压比例,得获适合的Bitmap(方法一)     * @param file File     * @param width 指定的宽度     * @param height 指定的度高     * @return Bitmap     */    public static Bitmap decodeStream(File file, int width, int height) {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeFile(file.getAbsolutePath(), options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options = new BitmapFactory.Options();        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeFile(file.getAbsolutePath(), options);    }    /**     * 根据指定的缩压比例,得获适合的Bitmap(方法二)     * @param inStream InputStream     * @param width 指定的宽度     * @param height 指定的度高     * @return Bitmap     * @throws IOException     */    public static Bitmap decodeStream(InputStream inStream, int width, int height) throws IOException {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        // 从输入流读取数据        byte[] data = StreamTool.read(inStream);        BitmapFactory.decodeByteArray(data, 0, data.length, options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeByteArray(data, 0, data.length);    }    /**     * 根据指定的缩压比例,得获适合的Bitmap(会错出的方法,仅用于测试)     * @param inStream     * @param width     * @param height     * @return     * @throws IOException     */    public static Bitmap decodeStreamError(InputStream inStream, int width, int height) throws IOException {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeStream(inStream, null, options);        int w = options.outWidth;        int h = options.outHeight;        // 从服务器端得获的图片巨细为:80x120        // 我们想要的图片巨细为:40x40        // 缩放比:120/40 = 3,也就是说我们要的图片巨细为原图的1/3        // 缩放比。由于是定固比例缩放,只用高或者宽其中一个数据行进盘算可即        int ratio = 1; // 默以为不缩放        if (w >= h && w > width) {            ratio = (int) (w / width);        } else if (w < h && h > height) {            ratio = (int) (h / height);        }        if (ratio <= 0) {            ratio = 1;        }        System.out.println("图片的缩放比例值ratio = " + ratio);        options.inJustDecodeBounds = false;        // 属性值inSampleSize表示缩略图巨细为原始图片巨细的几分之一,即如果这个值为2,        // 则掏出的缩略图的宽和高都是原始图片的1/2,图片巨细就为原始巨细的1/4。        options.inSampleSize = ratio;        return BitmapFactory.decodeStream(inStream, null, options);    }}


单位转换具工类

package com.everyone.android.utils;import android.content.Context;/** * 能功描述:单位转换具工类 * @author android_ls * */public class DensityUtil {    /**     * 将单位为dip的值转换成单位为px的值     * @param context Context     * @param dipValue dip值     * @return px值     */    public static int dip2px(Context context, float dipValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (dipValue * scale + 0.5f);    }    /**     * 将单位为px的值转换成单位为dip的值     * @param context Context     * @param pxValue 像素值     * @return dip值     */    public static int px2dip(Context context, float pxValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (pxValue / scale + 0.5f);    }    /**     * 将px值转换为sp值,保障文字巨细稳定     *      * @param pxValue     * @param fontScale(DisplayMetrics类中属性scaledDensity)     * @return     */    public static int px2sp(Context context, float pxValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (pxValue / scale + 0.5f);    }    /**     * 将sp值转换为px值,保障文字巨细稳定     *      * @param spValue     * @param fontScale(DisplayMetrics类中属性scaledDensity)     * @return     */    public static int sp2px(Context context, float spValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (spValue * scale + 0.5f);    }}


数据流理处具工类数据流理处具工类数据流理处具工类

package com.everyone.android.utils;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;/** * 能功描述:数据流理处具工类 * @author android_ls */public final class StreamTool {    /**     * 从输入流读取数据     *      * @param inStream     * @return     * @throws IOException     * @throws Exception     */    public static byte[] read(InputStream inStream) throws IOException {        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();        byte[] buffer = new byte[1024];        int len = 0;        while ((len = inStream.read(buffer)) != -1) {            outSteam.write(buffer, 0, len);        }        outSteam.close();        inStream.close();        return outSteam.toByteArray();    }}

五、络网模块改修的文件源码:

络网请求线程基类

package com.everyone.android.net;import java.io.IOException;import java.io.InputStream;import java.io.Serializable;import java.net.HttpURLConnection;import java.util.Map;import org.json.JSONException;import com.everyone.android.callback.ParseCallback;import com.everyone.android.callback.ResultCallback;import com.everyone.android.utils.Constant;import com.everyone.android.utils.LogUtil;import com.everyone.android.utils.StreamTool;/** * 能功描述:络网请求线程基类 * @author android_ls * */public abstract class AsyncBaseRequest implements Runnable, Serializable {    /**     *      */    private static final long serialVersionUID = 1L;    /**     * LOG打印标签     */    private static final String TAG = "AsyncBaseRequest";        /**     * 络网连接超时,默许值为5秒     */    protected int connectTimeout = 5 * 1000;    /**     * 络网数据读取超时,默许值为5秒     */    protected int readTimeout = 5 * 1000;    private boolean interrupted;    public boolean isInterrupted() {        return interrupted;    }    public void setInterrupted(boolean interrupted) {        this.interrupted = interrupted;    }    protected void setConnectTimeout(int connectTimeout) {        this.connectTimeout = connectTimeout;    }    protected void setReadTimeout(int readTimeout) {        this.readTimeout = readTimeout;    }    protected String requestUrl;    protected Map<String, String> parameter;    private ParseCallback parseHandler;    private ResultCallback requestCallback;    protected HttpURLConnection mHttpURLConn;    protected InputStream mInStream;    public AsyncBaseRequest(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) {        this.parseHandler = handler;        this.requestUrl = url;        this.parameter = parameter;        this.requestCallback = requestCallback;    }    /**     * 发送络网请求     *      * @return 络网请求返回的InputStream数据流     * @throws IOException     */    protected abstract InputStream getRequestResult() throws IOException;    @Override    public void run() {        if (interrupted) {            LogUtil.i(TAG, "问访络网前中断务业理处线程(止终)");            return;        }                try {            mInStream = getRequestResult();            if (mInStream != null) {                if (interrupted) {                    LogUtil.i(TAG, "读取数据前中断务业理处线程(止终)");                    return;                }                Object obj = null;                if(parseHandler != null){                    byte[] data = StreamTool.read(mInStream);                    if (interrupted) {                        LogUtil.i(TAG, "剖析数据前中断务业理处线程(止终)");                        return;                    }                                        String result = new String(data);                    obj = parseHandler.parse(result);                }                                if (interrupted) {                    LogUtil.i(TAG, "刷新UI前中断务业理处线程(止终)");                    return;                }                                if(obj != null){                    requestCallback.onSuccess(obj);                } else {                    requestCallback.onSuccess(mInStream);                }                           } else {                LogUtil.i(TAG, "get InputStream By HttpURLConnection return result is NULL.");                requestCallback.onFail(Constant.NETWORK_REQUEST_RETUN_NULL); // 络网请求返回NULL            }        } catch (JSONException e) {            requestCallback.onFail(Constant.NETWORK_REQUEST_RESULT_PARSE_ERROR); // 络网请求返回结果剖析错出            e.printStackTrace();        } catch (IOException e) {            requestCallback.onFail(Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO常异标识            e.printStackTrace();        }            }    public HttpURLConnection getRequestConn() {        return mHttpURLConn;    }}

通过HTTP议协发送GET请求

package com.everyone.android.net;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;import java.util.Map;import org.apache.http.protocol.HTTP;import com.everyone.android.callback.ParseCallback;import com.everyone.android.callback.ResultCallback;/** * 能功描述:通过HTTP议协发送GET请求 * @author android_ls * */public class AsyncHttpGet extends AsyncBaseRequest {    /**     *      */    private static final long serialVersionUID = 2L;    public AsyncHttpGet(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) throws IOException {        super(url, parameter, handler, requestCallback);    }    @Override    protected InputStream getRequestResult() throws IOException {        StringBuilder sb = new StringBuilder(requestUrl);        if (parameter != null && !parameter.isEmpty()) {            sb.append('?');            for (Map.Entry<String, String> entry : parameter.entrySet()) {                sb.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');            }            sb.deleteCharAt(sb.length() - 1);        }        URL url = new URL(sb.toString());        mHttpURLConn = (HttpURLConnection) url.openConnection();        mHttpURLConn.setConnectTimeout(connectTimeout);        mHttpURLConn.setRequestMethod("GET");        if (mHttpURLConn.getResponseCode() == HttpURLConnection.HTTP_OK) {            return mHttpURLConn.getInputStream();        }        return null;    }}


六、行运后的效果图:

图片双缓存这块,拖了良久,这一篇博文我花了一晚上间时,搞了一个宵通,于终写完了。天亮了,说:友人们,晚安!

文章结束给大家分享下程序员的一些笑话语录: 人工智能今天的发展水平:8乘8的国际象棋盘其实是一个体现思维与创意的强大媒介。象棋里蕴含了天文数字般的变化。卡斯帕罗夫指出,国际象棋的合法棋步共有1040。在棋局里每算度八步棋,里面蕴含的变化就已经超过银河系里的繁星总数。而地球上很少有任何数量达到这个级别。在金融危机之前,全世界的财富总和大约是1014人民币,而地球人口只有1010。棋盘上,所有可能的棋局总数达到10120,这超过了宇宙里所有原子的总数!经典语录网

更多相关文章

  1. Android的自定义图片按钮ImageButton【第一篇】
  2. Picasso之图片缓存机制
  3. 关于Android(安卓)EditText图文混排的总结
  4. Android使用huffman编码进行图片压缩
  5. Android图片缓存分析(一)
  6. Android中图片的三级缓存策略
  7. Android小项目——社交类app(低仿微信)
  8. Android:调用系统图库/裁剪图片
  9. 安卓图片反复压缩后为什么普遍会变绿而不是其它颜色?

随机推荐

  1. Android面试题(八) --原版
  2. 深入了解View实现原理以及自定义View详解
  3. [Android进阶笔记]Android触摸事件的拦截
  4. 常用的android开发框架有哪些
  5. PreferenceActivity
  6. android 截图
  7. 英特尔® 硬件加速执行管理器安装指南 —
  8. Android(安卓)WebView与JavaScript交互详
  9. Android(安卓)用户界面---定制组件(Custom
  10. Android(安卓)阿拉伯语言适配