Waterfall

1.1

package com.example.photowallfallsdemo;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Toast;

/**
 * 自定义的ScrollView,在其中动态地对图片进行添加。
 * 
 * @author guolin
 */
public class MyScrollView extends ScrollView implements OnTouchListener {

    /**
     * 每页要加载的图片数量
     */
    public static final int PAGE_SIZE = 15;

    /**
     * 记录当前已加载到第几页
     */
    private int page;

    /**
     * 每一列的宽度
     */
    private int columnWidth;

    /**
     * 当前第一列的高度
     */
    private int firstColumnHeight;

    /**
     * 当前第二列的高度
     */
    private int secondColumnHeight;

    /**
     * 当前第三列的高度
     */
    private int thirdColumnHeight;

    /**
     * 是否已加载过一次layout,这里onLayout中的初始化只需加载一次
     */
    private boolean loadOnce;

    /**
     * 对图片进行管理的工具类
     */
    private ImageLoader imageLoader;

    /**
     * 第一列的布局
     */
    private LinearLayout firstColumn;

    /**
     * 第二列的布局
     */
    private LinearLayout secondColumn;

    /**
     * 第三列的布局
     */
    private LinearLayout thirdColumn;

    /**
     * 记录所有正在下载或等待下载的任务。
     */
    private static Set<LoadImageTask> taskCollection;

    /**
     * MyScrollView下的直接子布局。
     */
    private static View scrollLayout;

    /**
     * MyScrollView布局的高度。
     */
    private static int scrollViewHeight;

    /**
     * 记录上垂直方向的滚动距离。
     */
    private static int lastScrollY = -1;

    /**
     * 记录所有界面上的图片,用以可以随时控制对图片的释放。
     */
    private List<ImageView> imageViewList = new ArrayList<ImageView>();

    /**
     * 在Handler中进行图片可见性检查的判断,以及加载更多图片的操作。
     */
    private static Handler handler = new Handler() {

        public void handleMessage(android.os.Message msg) {
            MyScrollView myScrollView = (MyScrollView) msg.obj;
            int scrollY = myScrollView.getScrollY();
            // 如果当前的滚动位置和上次相同,表示已停止滚动
            if (scrollY == lastScrollY) {
                // 当滚动的最底部,并且当前没有正在下载的任务时,开始加载下一页的图片
                if (scrollViewHeight + scrollY >= scrollLayout.getHeight()
                        && taskCollection.isEmpty()) {
                    myScrollView.loadMoreImages();
                }
                myScrollView.checkVisibility();
            } else {
                lastScrollY = scrollY;
                Message message = new Message();
                message.obj = myScrollView;
                // 5毫秒后再次对滚动位置进行判断
                handler.sendMessageDelayed(message, 5);
            }
        };

    };

    /**
     * MyScrollView的构造函数。
     * 
     * @param context
     * @param attrs
     */
    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        imageLoader = ImageLoader.getInstance();
        taskCollection = new HashSet<LoadImageTask>();
        setOnTouchListener(this);
    }

    /**
     * 进行一些关键性的初始化操作,获取MyScrollView的高度,以及得到第一列的宽度值。并在这里开始加载第一页的图片。
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed && !loadOnce) {
            scrollViewHeight = getHeight();
            scrollLayout = getChildAt(0);
            firstColumn = (LinearLayout) findViewById(R.id.first_column);
            secondColumn = (LinearLayout) findViewById(R.id.second_column);
            thirdColumn = (LinearLayout) findViewById(R.id.third_column);
            columnWidth = firstColumn.getWidth();
            loadOnce = true;
            loadMoreImages();
        }
    }

    /**
     * 监听用户的触屏事件,如果用户手指离开屏幕则开始进行滚动检测。
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            Message message = new Message();
            message.obj = this;
            handler.sendMessageDelayed(message, 5);
        }
        return false;
    }

    /**
     * 开始加载下一页的图片,每张图片都会开启一个异步线程去下载。
     */
    public void loadMoreImages() {
        if (hasSDCard()) {
            int startIndex = page * PAGE_SIZE;
            int endIndex = page * PAGE_SIZE + PAGE_SIZE;
            if (startIndex < Images.imageUrls.length) {
                Toast.makeText(getContext(), "正在加载...", Toast.LENGTH_SHORT)
                        .show();
                if (endIndex > Images.imageUrls.length) {
                    endIndex = Images.imageUrls.length;
                }
                for (int i = startIndex; i < endIndex; i++) {
                    LoadImageTask task = new LoadImageTask();
                    taskCollection.add(task);
                    task.execute(Images.imageUrls[i]);
                }
                page++;
            } else {
                Toast.makeText(getContext(), "已没有更多图片", Toast.LENGTH_SHORT)
                        .show();
            }
        } else {
            Toast.makeText(getContext(), "未发现SD卡", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空图。
     */
    public void checkVisibility() {
        for (int i = 0; i < imageViewList.size(); i++) {
            ImageView imageView = imageViewList.get(i);
            int borderTop = (Integer) imageView.getTag(R.string.border_top);
            int borderBottom = (Integer) imageView
                    .getTag(R.string.border_bottom);
            if (borderBottom > getScrollY()
                    && borderTop < getScrollY() + scrollViewHeight) {
                String imageUrl = (String) imageView.getTag(R.string.image_url);
                Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);
                if (bitmap != null) {
                    imageView.setImageBitmap(bitmap);
                } else {
                    LoadImageTask task = new LoadImageTask(imageView);
                    task.execute(imageUrl);
                }
            } else {
                imageView.setImageResource(R.drawable.empty_photo);
            }
        }
    }

    /**
     * 判断手机是否有SD卡。
     * 
     * @return 有SD卡返回true,没有返回false。
     */
    private boolean hasSDCard() {
        return Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState());
    }

    /**
     * 异步下载图片的任务。
     * 
     * @author guolin
     */
    class LoadImageTask extends AsyncTask<String, Void, Bitmap> {

        /**
         * 图片的URL地址
         */
        private String mImageUrl;

        /**
         * 可重复使用的ImageView
         */
        private ImageView mImageView;

        public LoadImageTask() {
        }

        /**
         * 将可重复使用的ImageView传入
         * 
         * @param imageView
         */
        public LoadImageTask(ImageView imageView) {
            mImageView = imageView;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            mImageUrl = params[0];
            Bitmap imageBitmap = imageLoader
                    .getBitmapFromMemoryCache(mImageUrl);
            if (imageBitmap == null) {
                imageBitmap = loadImage(mImageUrl);
            }
            return imageBitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (bitmap != null) {
                double ratio = bitmap.getWidth() / (columnWidth * 1.0);
                int scaledHeight = (int) (bitmap.getHeight() / ratio);
                addImage(bitmap, columnWidth, scaledHeight);
            }
            taskCollection.remove(this);
        }

        /**
         * 根据传入的URL,对图片进行加载。如果这张图片已经存在于SD卡中,则直接从SD卡里读取,否则就从网络上下载。
         * 
         * @param imageUrl
         *            图片的URL地址
         * @return 加载到内存的图片。
         */
        private Bitmap loadImage(String imageUrl) {
            File imageFile = new File(getImagePath(imageUrl));
            if (!imageFile.exists()) {
                downloadImage(imageUrl);
            }
            if (imageUrl != null) {
                Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(
                        imageFile.getPath(), columnWidth);
                if (bitmap != null) {
                    imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);
                    return bitmap;
                }
            }
            return null;
        }

        /**
         * 向ImageView中添加一张图片
         * 
         * @param bitmap
         *            待添加的图片
         * @param imageWidth
         *            图片的宽度
         * @param imageHeight
         *            图片的高度
         */
        private void addImage(Bitmap bitmap, int imageWidth, int imageHeight) {
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    imageWidth, imageHeight);
            if (mImageView != null) {
                mImageView.setImageBitmap(bitmap);
            } else {
                ImageView imageView = new ImageView(getContext());
                imageView.setLayoutParams(params);
                imageView.setImageBitmap(bitmap);
                imageView.setScaleType(ScaleType.FIT_XY);
                imageView.setPadding(5, 5, 5, 5);
                imageView.setTag(R.string.image_url, mImageUrl);
                findColumnToAdd(imageView, imageHeight).addView(imageView);
                imageViewList.add(imageView);
            }
        }

        /**
         * 找到此时应该添加图片的一列。原则就是对三列的高度进行判断,当前高度最小的一列就是应该添加的一列。
         * 
         * @param imageView
         * @param imageHeight
         * @return 应该添加图片的一列
         */
        private LinearLayout findColumnToAdd(ImageView imageView,
                int imageHeight) {
            if (firstColumnHeight <= secondColumnHeight) {
                if (firstColumnHeight <= thirdColumnHeight) {
                    imageView.setTag(R.string.border_top, firstColumnHeight);
                    firstColumnHeight += imageHeight;
                    imageView.setTag(R.string.border_bottom, firstColumnHeight);
                    return firstColumn;
                }
                imageView.setTag(R.string.border_top, thirdColumnHeight);
                thirdColumnHeight += imageHeight;
                imageView.setTag(R.string.border_bottom, thirdColumnHeight);
                return thirdColumn;
            } else {
                if (secondColumnHeight <= thirdColumnHeight) {
                    imageView.setTag(R.string.border_top, secondColumnHeight);
                    secondColumnHeight += imageHeight;
                    imageView
                            .setTag(R.string.border_bottom, secondColumnHeight);
                    return secondColumn;
                }
                imageView.setTag(R.string.border_top, thirdColumnHeight);
                thirdColumnHeight += imageHeight;
                imageView.setTag(R.string.border_bottom, thirdColumnHeight);
                return thirdColumn;
            }
        }

        /**
         * 将图片下载到SD卡缓存起来。
         * 
         * @param imageUrl
         *            图片的URL地址。
         */
        private void downloadImage(String imageUrl) {
            if (Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)) {
                Log.d("TAG", "monted sdcard");
            } else {
                Log.d("TAG", "has no sdcard");
            }
            HttpURLConnection con = null;
            FileOutputStream fos = null;
            BufferedOutputStream bos = null;
            BufferedInputStream bis = null;
            File imageFile = null;
            try {
                URL url = new URL(imageUrl);
                con = (HttpURLConnection) url.openConnection();
                con.setConnectTimeout(5 * 1000);
                con.setReadTimeout(15 * 1000);
                con.setDoInput(true);
                con.setDoOutput(true);
                bis = new BufferedInputStream(con.getInputStream());
                imageFile = new File(getImagePath(imageUrl));
                fos = new FileOutputStream(imageFile);
                bos = new BufferedOutputStream(fos);
                byte[] b = new byte[1024];
                int length;
                while ((length = bis.read(b)) != -1) {
                    bos.write(b, 0, length);
                    bos.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (bos != null) {
                        bos.close();
                    }
                    if (con != null) {
                        con.disconnect();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (imageFile != null) {
                Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(
                        imageFile.getPath(), columnWidth);
                if (bitmap != null) {
                    imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);
                }
            }
        }

        /**
         * 获取图片的本地存储路径。
         * 
         * @param imageUrl
         *            图片的URL地址。
         * @return 图片的本地存储路径。
         */
        private String getImagePath(String imageUrl) {
            int lastSlashIndex = imageUrl.lastIndexOf("/");
            String imageName = imageUrl.substring(lastSlashIndex + 1);
            String imageDir = Environment.getExternalStorageDirectory()
                    .getPath() + "/PhotoWallFalls/";
            File file = new File(imageDir);
            if (!file.exists()) {
                file.mkdirs();
            }
            String imagePath = imageDir + imageName;
            return imagePath;
        }
    }

}

1.2

package com.example.photowallfallsdemo;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;

/**
 * 对图片进行管理的工具类。
 * 
 * @author Tony
 */
public class ImageLoader {

    /**
     * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。
     */
    private static LruCache<String, Bitmap> mMemoryCache;

    /**
     * ImageLoader的实例。
     */
    private static ImageLoader mImageLoader;

    private ImageLoader() {
        // 获取应用程序最大可用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 8;
        // 设置图片缓存大小为程序最大可用内存的1/8
        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount();
            }
        };
    }

    /**
     * 获取ImageLoader的实例。
     * 
     * @return ImageLoader的实例。
     */
    public static ImageLoader getInstance() {
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader();
        }
        return mImageLoader;
    }

    /**
     * 将一张图片存储到LruCache中。
     * 
     * @param key
     *            LruCache的键,这里传入图片的URL地址。
     * @param bitmap
     *            LruCache的键,这里传入从网络上下载的Bitmap对象。
     */
    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemoryCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }

    /**
     * 从LruCache中获取一张图片,如果不存在就返回null。
     * 
     * @param key
     *            LruCache的键,这里传入图片的URL地址。
     * @return 对应传入键的Bitmap对象,或者null。
     */
    public Bitmap getBitmapFromMemoryCache(String key) {
        return mMemoryCache.get(key);
    }

    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth) {
        // 源图片的宽度
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (width > reqWidth) {
            // 计算出实际宽度和目标宽度的比率
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = widthRatio;
        }
        return inSampleSize;
    }

    public static Bitmap decodeSampledBitmapFromResource(String pathName,
            int reqWidth) {
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(pathName, options);
        // 调用上面定义的方法计算inSampleSize值
        options.inSampleSize = calculateInSampleSize(options, reqWidth);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(pathName, options);
    }

}

2.1

package com.example.demo_zhy_18_networkimageloader;
import android.content.Context;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.zhy.utils.ImageLoader;
import com.zhy.utils.ImageLoader.Type;
import com.zhy.utils.Images;
public class ListImgsFragment extends Fragment
{
    private GridView mGridView;
    private String[] mUrlStrs = Images.imageThumbUrls;
    private ImageLoader mImageLoader;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        mImageLoader = ImageLoader.getInstance(3, Type.LIFO);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.fragment_list_imgs, container,
                false);
        mGridView = (GridView) view.findViewById(R.id.id_gridview);
        setUpAdapter();
        return view;
    }
    private void setUpAdapter()
    {
        if (getActivity() == null || mGridView == null)
            return;
        if (mUrlStrs != null)
        {
            mGridView.setAdapter(new ListImgItemAdaper(getActivity(), 0,
                    mUrlStrs));
        } else
        {
            mGridView.setAdapter(null);
        }
    }
    private class ListImgItemAdaper extends ArrayAdapter<String>
    {
        public ListImgItemAdaper(Context context, int resource, String[] datas)
        {
            super(getActivity(), 0, datas);
            Log.e("TAG", "ListImgItemAdaper");
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            if (convertView == null)
            {
                convertView = getActivity().getLayoutInflater().inflate(
                        R.layout.item_fragment_list_imgs, parent, false);
            }
            ImageView imageview = (ImageView) convertView
                    .findViewById(R.id.id_img);
            imageview.setImageResource(R.drawable.pictures_no);
            mImageLoader.loadImage(getItem(position), imageview, true);
            return convertView;
        }
    }
}

2.2

package com.zhy.utils;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.LruCache;
import android.util.Log;
import android.widget.ImageView;
import com.zhy.utils.ImageSizeUtil.ImageSize;
public class ImageLoader
{
    private static ImageLoader mInstance;

    private LruCache<String, Bitmap> mLruCache;

    private ExecutorService mThreadPool;
    private static final int DEAFULT_THREAD_COUNT = 1;

    private Type mType = Type.LIFO;

    private LinkedList<Runnable> mTaskQueue;

    private Thread mPoolThread;
    private Handler mPoolThreadHandler;

    private Handler mUIHandler;
    private Semaphore mSemaphorePoolThreadHandler = new Semaphore(0);
    private Semaphore mSemaphoreThreadPool;
    private boolean isDiskCacheEnable = true;
    private static final String TAG = "ImageLoader";
    public enum Type
    {
        FIFO, LIFO;
    }
    private ImageLoader(int threadCount, Type type)
    {
        init(threadCount, type);
    }

    private void init(int threadCount, Type type)
    {
        initBackThread();

        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheMemory = maxMemory / 8;
        mLruCache = new LruCache<String, Bitmap>(cacheMemory)
        {
            @Override
            protected int sizeOf(String key, Bitmap value)
            {
                return value.getRowBytes() * value.getHeight();
            }
        };

        mThreadPool = Executors.newFixedThreadPool(threadCount);
        mTaskQueue = new LinkedList<Runnable>();
        mType = type;
        mSemaphoreThreadPool = new Semaphore(threadCount);
    }

    private void initBackThread()
    {

        mPoolThread = new Thread()
        {
            @Override
            public void run()
            {
                Looper.prepare();
                mPoolThreadHandler = new Handler()
                {
                    @Override
                    public void handleMessage(Message msg)
                    {

                        mThreadPool.execute(getTask());
                        try
                        {
                            mSemaphoreThreadPool.acquire();
                        } catch (InterruptedException e)
                        {
                        }
                    }
                };

                mSemaphorePoolThreadHandler.release();
                Looper.loop();
            };
        };
        mPoolThread.start();
    }
    public static ImageLoader getInstance()
    {
        if (mInstance == null)
        {
            synchronized (ImageLoader.class)
            {
                if (mInstance == null)
                {
                    mInstance = new ImageLoader(DEAFULT_THREAD_COUNT, Type.LIFO);
                }
            }
        }
        return mInstance;
    }
    public static ImageLoader getInstance(int threadCount, Type type)
    {
        if (mInstance == null)
        {
            synchronized (ImageLoader.class)
            {
                if (mInstance == null)
                {
                    mInstance = new ImageLoader(threadCount, type);
                }
            }
        }
        return mInstance;
    }

    public void loadImage(final String path, final ImageView imageView,
            final boolean isFromNet)
    {
        imageView.setTag(path);
        if (mUIHandler == null)
        {
            mUIHandler = new Handler()
            {
                public void handleMessage(Message msg)
                {

                    ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
                    Bitmap bm = holder.bitmap;
                    ImageView imageview = holder.imageView;
                    String path = holder.path;

                    if (imageview.getTag().toString().equals(path))
                    {
                        imageview.setImageBitmap(bm);
                    }
                };
            };
        }

        Bitmap bm = getBitmapFromLruCache(path);
        if (bm != null)
        {
            refreashBitmap(path, imageView, bm);
        } else
        {
            addTask(buildTask(path, imageView, isFromNet));
        }
    }

    private Runnable buildTask(final String path, final ImageView imageView,
            final boolean isFromNet)
    {
        return new Runnable()
        {
            @Override
            public void run()
            {
                Bitmap bm = null;
                if (isFromNet)
                {
                    File file = getDiskCacheDir(imageView.getContext(),
                            md5(path));
                    if (file.exists())
                    {
                        Log.e(TAG, "find image :" + path + " in disk cache .");
                        bm = loadImageFromLocal(file.getAbsolutePath(),
                                imageView);
                    } else
                    {
                        if (isDiskCacheEnable)
                        {
                            boolean downloadState = DownloadImgUtils
                                    .downloadImgByUrl(path, file);
                            if (downloadState)
                            {
                                Log.e(TAG,
                                        "download image :" + path
                                                + " to disk cache . path is "
                                                + file.getAbsolutePath());
                                bm = loadImageFromLocal(file.getAbsolutePath(),
                                        imageView);
                            }
                        } else

                        {
                            Log.e(TAG, "load image :" + path + " to memory.");
                            bm = DownloadImgUtils.downloadImgByUrl(path,
                                    imageView);
                        }
                    }
                } else
                {
                    bm = loadImageFromLocal(path, imageView);
                }

                addBitmapToLruCache(path, bm);
                refreashBitmap(path, imageView, bm);
                mSemaphoreThreadPool.release();
            }
        };
    }
    private Bitmap loadImageFromLocal(final String path,
            final ImageView imageView)
    {
        Bitmap bm;



        ImageSize imageSize = ImageSizeUtil.getImageViewSize(imageView);

        bm = decodeSampledBitmapFromPath(path, imageSize.width,
                imageSize.height);
        return bm;
    }

    private Runnable getTask()
    {
        if (mType == Type.FIFO)
        {
            return mTaskQueue.removeFirst();
        } else if (mType == Type.LIFO)
        {
            return mTaskQueue.removeLast();
        }
        return null;
    }

    public String md5(String str)
    {
        byte[] digest = null;
        try
        {
            MessageDigest md = MessageDigest.getInstance("md5");
            digest = md.digest(str.getBytes());
            return bytes2hex02(digest);
        } catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public String bytes2hex02(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder();
        String tmp = null;
        for (byte b : bytes)
        {

            tmp = Integer.toHexString(0xFF & b);
            if (tmp.length() == 1)
            {
                tmp = "0" + tmp;
            }
            sb.append(tmp);
        }
        return sb.toString();
    }
    private void refreashBitmap(final String path, final ImageView imageView,
            Bitmap bm)
    {
        Message message = Message.obtain();
        ImgBeanHolder holder = new ImgBeanHolder();
        holder.bitmap = bm;
        holder.path = path;
        holder.imageView = imageView;
        message.obj = holder;
        mUIHandler.sendMessage(message);
    }

    protected void addBitmapToLruCache(String path, Bitmap bm)
    {
        if (getBitmapFromLruCache(path) == null)
        {
            if (bm != null)
                mLruCache.put(path, bm);
        }
    }

    protected Bitmap decodeSampledBitmapFromPath(String path, int width,
            int height)
    {

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
                width, height);

        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        return bitmap;
    }
    private synchronized void addTask(Runnable runnable)
    {
        mTaskQueue.add(runnable);

        try
        {
            if (mPoolThreadHandler == null)
                mSemaphorePoolThreadHandler.acquire();
        } catch (InterruptedException e)
        {
        }
        mPoolThreadHandler.sendEmptyMessage(0x110);
    }

    public File getDiskCacheDir(Context context, String uniqueName)
    {
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState()))
        {
            cachePath = context.getExternalCacheDir().getPath();
        } else
        {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }

    private Bitmap getBitmapFromLruCache(String key)
    {
        return mLruCache.get(key);
    }
    private class ImgBeanHolder
    {
        Bitmap bitmap;
        ImageView imageView;
        String path;
    }
}

2.3

package com.zhy.utils;
import java.lang.reflect.Field;
import android.graphics.BitmapFactory.Options;
import android.util.DisplayMetrics;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
public class ImageSizeUtil
{

    public static int caculateInSampleSize(Options options, int reqWidth,
            int reqHeight)
    {
        int width = options.outWidth;
        int height = options.outHeight;
        int inSampleSize = 1;
        if (width > reqWidth || height > reqHeight)
        {
            int widthRadio = Math.round(width * 1.0f / reqWidth);
            int heightRadio = Math.round(height * 1.0f / reqHeight);
            inSampleSize = Math.max(widthRadio, heightRadio);
        }
        return inSampleSize;
    }

    public static ImageSize getImageViewSize(ImageView imageView)
    {
        ImageSize imageSize = new ImageSize();
        DisplayMetrics displayMetrics = imageView.getContext().getResources()
                .getDisplayMetrics();
        LayoutParams lp = imageView.getLayoutParams();
        int width = imageView.getWidth();
        if (width <= 0)
        {
            width = lp.width;
        }
        if (width <= 0)
        {

            width = getImageViewFieldValue(imageView, "mMaxWidth");
        }
        if (width <= 0)
        {
            width = displayMetrics.widthPixels;
        }
        int height = imageView.getHeight();
        if (height <= 0)
        {
            height = lp.height;
        }
        if (height <= 0)
        {
            height = getImageViewFieldValue(imageView, "mMaxHeight");
        }
        if (height <= 0)
        {
            height = displayMetrics.heightPixels;
        }
        imageSize.width = width;
        imageSize.height = height;
        return imageSize;
    }
    public static class ImageSize
    {
        int width;
        int height;
    }

    private static int getImageViewFieldValue(Object object, String fieldName)
    {
        int value = 0;
        try
        {
            Field field = ImageView.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            int fieldValue = field.getInt(object);
            if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE)
            {
                value = fieldValue;
            }
        } catch (Exception e)
        {
        }
        return value;
    }
}

2.4

package com.zhy.utils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.util.Log;
import android.widget.ImageView;
import com.zhy.utils.ImageSizeUtil.ImageSize;
public class DownloadImgUtils
{

    public static boolean downloadImgByUrl(String urlStr, File file)
    {
        FileOutputStream fos = null;
        InputStream is = null;
        try
        {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            is = conn.getInputStream();
            fos = new FileOutputStream(file);
            byte[] buf = new byte[512];
            int len = 0;
            while ((len = is.read(buf)) != -1)
            {
                fos.write(buf, 0, len);
            }
            fos.flush();
            return true;
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                if (is != null)
                    is.close();
            } catch (IOException e)
            {
            }
            try
            {
                if (fos != null)
                    fos.close();
            } catch (IOException e)
            {
            }
        }
        return false;
    }

    public static Bitmap downloadImgByUrl(String urlStr, ImageView imageview)
    {
        FileOutputStream fos = null;
        InputStream is = null;
        try
        {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            is = new BufferedInputStream(conn.getInputStream());
            is.mark(is.available());
            Options opts = new Options();
            opts.inJustDecodeBounds = true;
            Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);

            ImageSize imageViewSize = ImageSizeUtil.getImageViewSize(imageview);
            opts.inSampleSize = ImageSizeUtil.caculateInSampleSize(opts,
                    imageViewSize.width, imageViewSize.height);
            opts.inJustDecodeBounds = false;
            is.reset();
            bitmap = BitmapFactory.decodeStream(is, null, opts);
            conn.disconnect();
            return bitmap;
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                if (is != null)
                    is.close();
            } catch (IOException e)
            {
            }
            try
            {
                if (fos != null)
                    fos.close();
            } catch (IOException e)
            {
            }
        }
        return null;
    }
}

3.1

package com.cascade;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;

import com.cascade.DrawableManager.ImageCallback;

public class TestCascadeActivity extends Activity {
    private static final String TAG = "TestCascadeActivity";

    private LinearLayout llCcasecade;
    private LinearLayout lvCasecade1;
    private LinearLayout lvCasecade2;
    private LinearLayout lvCasecade3;

    private Display display;
    private AssetManager assetManager;
    private List<String> iamgePaths;
    private static final String imgspath = "imgs";
    private int casecadeWidth;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_temp);
        display = this.getWindowManager().getDefaultDisplay();
        casecadeWidth = display.getWidth()/3;
        assetManager = this.getAssets();
        findView();
    }

    private void findView(){
        llCcasecade = (LinearLayout)this.findViewById(R.id.llCcasecade);
        lvCasecade1 = (LinearLayout)this.findViewById(R.id.casecade1);
        lvCasecade2 = (LinearLayout)this.findViewById(R.id.casecade2);
        lvCasecade3 = (LinearLayout)this.findViewById(R.id.casecade3);
        LayoutParams lp1 = lvCasecade1.getLayoutParams();
        lp1.width = casecadeWidth;
        lvCasecade1.setLayoutParams(lp1);

        LayoutParams lp2 = lvCasecade2.getLayoutParams();
        lp2.width = casecadeWidth;
        lvCasecade2.setLayoutParams(lp2);

        LayoutParams lp3 = lvCasecade3.getLayoutParams();
        lp3.width = casecadeWidth;
        lvCasecade3.setLayoutParams(lp3);

        try {
            iamgePaths = Arrays.asList(assetManager.list("imgs"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        int j = 0;
        for (int i = 0; i < iamgePaths.size(); i++) {
            addImgToCasecade(iamgePaths.get(i), j);
            j++;
            if(j>=3) j = 0;
        }

    }

    private void addImgToCasecade(String filename,int j){
        ImageView iv = (ImageView)LayoutInflater.from(this).inflate(R.layout.item_temp, null);
        if(j==0){
            lvCasecade1.addView(iv);
        }else if(j==1){
            lvCasecade2.addView(iv);
        }else{
            lvCasecade3.addView(iv);
        }
        String imgPath = imgspath+"/"+filename;
        iv.setTag(imgPath);
        Drawable drawable = DrawableManager.getInstance().fetchDrawableOnThread(imgPath, assetManager, new ImageCallback() {
            @Override
            public void imageLoaded(Drawable imageDrawable, String imageUrl) {
                ImageView iv = (ImageView)llCcasecade.findViewWithTag(imageUrl);
                if(iv!=null && imageDrawable!=null){
                    int oldwidth = imageDrawable.getIntrinsicWidth();
                    int oldheight = imageDrawable.getIntrinsicHeight();
                    LayoutParams lp = iv.getLayoutParams();
                    lp.height = (oldheight * casecadeWidth)/oldwidth;
                    iv.setPadding(0, 2, 0, 0);
                    iv.setLayoutParams(lp);
                    iv.setImageDrawable(imageDrawable);
                }
            }
        });
        if(drawable!=null){
            int oldwidth = drawable.getIntrinsicWidth();
            int oldheight = drawable.getIntrinsicHeight();
            LayoutParams lp = iv.getLayoutParams();
            lp.height = (oldheight * casecadeWidth)/oldwidth;
            iv.setPadding(0, 2, 0, 0);
            iv.setLayoutParams(lp);
            iv.setImageDrawable(drawable);
        }

    }

}

3.2

package com.cascade;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class DrawableManager {

    private static Map<String, Drawable> drawableMap = new LinkedHashMap<String, Drawable>();
    private static DrawableManager instance;

    private DrawableManager() {
    }

    public static DrawableManager getInstance() {
        if (instance == null) {
            instance = new DrawableManager();
        }
        return instance;
    }

    public void clear() {
        if (drawableMap != null) {
            drawableMap.clear();
            drawableMap = null;
        }
        Log.d(this.getClass().getSimpleName(), "clear image hashmap");
    }


    public Drawable fetchDrawableOnThread(final String urlString,final AssetManager assetManager,
            final ImageCallback imageCallback) {
        if (drawableMap == null) {
            drawableMap = new HashMap<String, Drawable>();
        }
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageCallback.imageLoaded((Drawable) message.obj, urlString);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                Drawable drawable = fetchDrawable(urlString,assetManager);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
        return null;
    }


    private Drawable fetchDrawable(String urlString,AssetManager assetManager) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        InputStream is = null;
        try {
            is = assetManager.open(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");
            if (drawableMap == null) {
                drawableMap = new HashMap<String, Drawable>();
            }
            drawableMap.put(urlString, drawable);
            return drawable;
        } catch (Exception e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        } finally{//关闭流
            try {
                if(is!=null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    public Drawable getDrawable(String urlkey) {
        return drawableMap.get(urlkey);
    }

    public interface ImageCallback {
        public void imageLoaded(Drawable imageDrawable, String imageUrl);
    }

     public void remove(String key){
         if(drawableMap.containsKey(key))
             drawableMap.remove(key);
     }
}

4.1

package com.dodowaterfall;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.dodowaterfall.LazyScrollView.OnScrollListener;

import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity {

    private LazyScrollView waterfall_scroll;
    private LinearLayout waterfall_container;
    private ArrayList<LinearLayout> waterfall_items;
    private Display display;
    private AssetManager assetManager;
    private List<String> image_filenames;
    private final String image_path = "images";

    private int itemWidth;

    private int column_count = 3;// 显示列数
    private int page_count = 15;// 每次加载15张图片

    private int current_page = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        display = this.getWindowManager().getDefaultDisplay();
        itemWidth = display.getWidth() / column_count;// 根据屏幕大小计算每列大小
        assetManager = this.getAssets();

        InitLayout();

    }

    private void InitLayout() {
        waterfall_scroll = (LazyScrollView) findViewById(R.id.waterfall_scroll);
        waterfall_scroll.getView();
        waterfall_scroll.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onTop() {
                // 滚动到最顶端
                Log.d("LazyScroll", "Scroll to top");
            }

            @Override
            public void onScroll() {
                // 滚动中
                Log.d("LazyScroll", "Scroll");
            }

            @Override
            public void onBottom() {
                // 滚动到最低端
                AddItemToContainer(++current_page, page_count);
            }
        });

        waterfall_container = (LinearLayout) this
                .findViewById(R.id.waterfall_container);
        waterfall_items = new ArrayList<LinearLayout>();

        for (int i = 0; i < column_count; i++) {
            LinearLayout itemLayout = new LinearLayout(this);
            LinearLayout.LayoutParams itemParam = new LinearLayout.LayoutParams(
                    itemWidth, LayoutParams.WRAP_CONTENT);
            // itemParam.width = itemWidth;
            // itemParam.height = LayoutParams.WRAP_CONTENT;
            itemLayout.setPadding(2, 2, 2, 2);
            itemLayout.setOrientation(LinearLayout.VERTICAL);

            itemLayout.setLayoutParams(itemParam);
            waterfall_items.add(itemLayout);
            waterfall_container.addView(itemLayout);
        }

        // 加载所有图片路径

        try {
            image_filenames = Arrays.asList(assetManager.list(image_path));

        } catch (IOException e) {
            e.printStackTrace();
        }
        // 第一次加载
        AddItemToContainer(current_page, page_count);
    }

    private void AddItemToContainer(int pageindex, int pagecount) {
        int j = 0;
        int imagecount = image_filenames.size();
        for (int i = pageindex * pagecount; i < pagecount * (pageindex + 1)
                && i < imagecount; i++) {
            j = j >= column_count ? j = 0 : j;
            AddImage(image_filenames.get(i), j++);

        }

    }

    private void AddImage(String filename, int columnIndex) {
        ImageView item = (ImageView) LayoutInflater.from(this).inflate(
                R.layout.waterfallitem, null);
        waterfall_items.get(columnIndex).addView(item);

        TaskParam param = new TaskParam();
        param.setAssetManager(assetManager);
        param.setFilename(image_path + "/" + filename);
        param.setItemWidth(itemWidth);
        ImageLoaderTask task = new ImageLoaderTask(item);
        task.execute(param);

    }
}

4.2

package com.dodowaterfall;
//来自:http://blog.csdn.net/listening_music/article/details/7192629
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;

public class LazyScrollView extends ScrollView{
    private static final String tag="LazyScrollView";
    private Handler handler;
    private View view;
    public LazyScrollView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public LazyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    public LazyScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    //这个获得总的高度
    public int computeVerticalScrollRange(){
        return super.computeHorizontalScrollRange();
    }
    public int computeVerticalScrollOffset(){
        return super.computeVerticalScrollOffset();
    }
    private void init(){

        this.setOnTouchListener(onTouchListener);
        handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                // process incoming messages here
                super.handleMessage(msg);
                switch(msg.what){
                case 1:
                    if(view.getMeasuredHeight() <= getScrollY() + getHeight()) {
                        if(onScrollListener!=null){
                            onScrollListener.onBottom();
                        }

                    }else if(getScrollY()==0){
                        if(onScrollListener!=null){
                            onScrollListener.onTop();
                        }
                    }
                    else{
                        if(onScrollListener!=null){
                            onScrollListener.onScroll();
                        }
                    }
                    break;
                default:
                    break;
                }
            }
        };

    }

      OnTouchListener onTouchListener=new OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_UP:
                    if(view!=null&&onScrollListener!=null){
                        handler.sendMessageDelayed(handler.obtainMessage(1), 200);
                    }
                    break;

                default:
                    break;
                }
                return false;
            }

        };

        /**
         * 获得参考的View,主要是为了获得它的MeasuredHeight,然后和滚动条的ScrollY+getHeight作比较。
         */
        public void getView(){
            this.view=getChildAt(0);
            if(view!=null){
                init();
            }
        }

        /**
         * 定义接口
         * @author admin
         *
         */
        public interface OnScrollListener{
            void onBottom();
            void onTop();
            void onScroll();
        }
        private OnScrollListener onScrollListener;
        public void setOnScrollListener(OnScrollListener onScrollListener){
            this.onScrollListener=onScrollListener;
        }
}

4.3

package com.dodowaterfall;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;

public class ImageLoaderTask extends AsyncTask<TaskParam, Void, Bitmap> {

    private TaskParam param;
    private final WeakReference<ImageView> imageViewReference; // 防止内存溢出

    public ImageLoaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);

    }

    @Override
    protected Bitmap doInBackground(TaskParam... params) {

        param = params[0];
        return loadImageFile(param.getFilename(), param.getAssetManager());
    }

    private Bitmap loadImageFile(final String filename,
            final AssetManager manager) {
        InputStream is = null;
        try {

            Bitmap bmp = BitmapCache.getInstance().getBitmap(filename,
                    param.getAssetManager());
            return bmp;
        } catch (Exception e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            if (imageView != null) {
                if (bitmap != null) {
                    int width = bitmap.getWidth();// 获取真实宽高
                    int height = bitmap.getHeight();
                    LayoutParams lp = imageView.getLayoutParams();
                    lp.height = (height * param.getItemWidth()) / width;// 调整高度

                    imageView.setLayoutParams(lp);

                    imageView.setImageBitmap(bitmap);

                }

            }
        }
    }
}

4.4

package com.dodowaterfall;

import android.content.res.AssetManager;

public class TaskParam {
    private String filename;
    private AssetManager assetManager;
    private int ItemWidth;

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public AssetManager getAssetManager() {
        return assetManager;
    }

    public void setAssetManager(AssetManager assetManager) {
        this.assetManager = assetManager;
    }

    public int getItemWidth() {
        return ItemWidth;
    }

    public void setItemWidth(int itemWidth) {
        ItemWidth = itemWidth;
    }
}

4.5

package com.dodowaterfall;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Hashtable;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
 * 防止溢出
 *
 */
public class BitmapCache {
    static private BitmapCache cache;
    /** 用于Chche内容的存储 */
    private Hashtable<String, BtimapRef> bitmapRefs;
    /** 垃圾Reference的队列(所引用的对象已经被回收,则将该引用存入队列中) */
    private ReferenceQueue<Bitmap> q;

    /**
     * 继承SoftReference,使得每一个实例都具有可识别的标识。
     */
    private class BtimapRef extends SoftReference<Bitmap> {
        private String _key = "";

        public BtimapRef(Bitmap bmp, ReferenceQueue<Bitmap> q, String key) {
            super(bmp, q);
            _key = key;
        }
    }

    private BitmapCache() {
        bitmapRefs = new Hashtable<String, BtimapRef>();
        q = new ReferenceQueue<Bitmap>();

    }

    /**
     * 取得缓存器实例
     */
    public static BitmapCache getInstance() {
        if (cache == null) {
            cache = new BitmapCache();
        }
        return cache;

    }

    /**
     * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用
     */
    private void addCacheBitmap(Bitmap bmp, String key) {
        cleanCache();// 清除垃圾引用
        BtimapRef ref = new BtimapRef(bmp, q, key);
        bitmapRefs.put(key, ref);
    }

    /**
     * 依据所指定的文件名获取图片
     */
    public Bitmap getBitmap(String filename, AssetManager assetManager) {

        Bitmap bitmapImage = null;
        // 缓存中是否有该Bitmap实例的软引用,如果有,从软引用中取得。
        if (bitmapRefs.containsKey(filename)) {
            BtimapRef ref = (BtimapRef) bitmapRefs.get(filename);
            bitmapImage = (Bitmap) ref.get();
        }
        // 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,
        // 并保存对这个新建实例的软引用
        if (bitmapImage == null) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inTempStorage = new byte[16 * 1024];

            // bitmapImage = BitmapFactory.decodeFile(filename, options);
            BufferedInputStream buf;
            try {
                buf = new BufferedInputStream(assetManager.open(filename));
                bitmapImage = BitmapFactory.decodeStream(buf);
                this.addCacheBitmap(bitmapImage, filename);
            } catch (IOException e) {

                e.printStackTrace();
            }

        }

        return bitmapImage;
    }

    private void cleanCache() {
        BtimapRef ref = null;
        while ((ref = (BtimapRef) q.poll()) != null) {
            bitmapRefs.remove(ref._key);
        }
    }

    // 清除Cache内的全部内容
    public void clearCache() {
        cleanCache();
        bitmapRefs.clear();
        System.gc();
        System.runFinalization();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值