安卓图片异步加载

Android图片的异步加载,主要原理:

加载图片时先查看缓存中时候存在该图片,如果存在则返回该图片,否则先加载载一个默认的占位图片,同时创建一个通过网络获取图片的任务并添加,任务完成后放松消息给主线程更新界面。

使用方法:

01.AsynImageLoader asynImageLoader = new AsynImageLoader();  
02.asynImageLoader.showImageAsyn(imageView, imageUrl, resId);  

类代码:

01.package com.wangge.uumao.http;  
02.  
03.import java.lang.ref.SoftReference;  
04.import java.util.ArrayList;  
05.import java.util.HashMap;  
06.import java.util.List;  
07.import java.util.Map;  
08.  
09.import android.graphics.Bitmap;  
10.import android.os.Handler;  
11.import android.os.Message;  
12.import android.util.Log;  
13.import android.widget.ImageView;  
14.  
15.import com.wangge.uumao.util.PicUtil;  
16.  
17.public class AsynImageLoader {  
18.    private static final String TAG = "AsynImageLoader";  
19.    // 缓存下载过的图片的Map  
20.    private Map<String, SoftReference<Bitmap>> caches;  
21.    // 任务队列  
22.    private List<Task> taskQueue;  
23.    private boolean isRunning = false;  
24.      
25.    public AsynImageLoader(){  
26.        // 初始化变量  
27.        caches = new HashMap<String, SoftReference<Bitmap>>();  
28.        taskQueue = new ArrayList<AsynImageLoader.Task>();  
29.        // 启动图片下载线程  
30.        isRunning = true;  
31.        new Thread(runnable).start();  
32.    }  
33.      
34.    /** 
35.     *  
36.     * @param imageView 需要延迟加载图片的对象 
37.     * @param url 图片的URL地址 
38.     * @param resId 图片加载过程中显示的图片资源 
39.     */  
40.    public void showImageAsyn(ImageView imageView, String url, int resId){  
41.        imageView.setTag(url);  
42.        Bitmap bitmap = loadImageAsyn(url, getImageCallback(imageView, resId));  
43.          
44.        if(bitmap == null){  
45.            imageView.setImageResource(resId);  
46.        }else{  
47.            imageView.setImageBitmap(bitmap);  
48.        }  
49.    }  
50.      
51.    public Bitmap loadImageAsyn(String path, ImageCallback callback){  
52.        // 判断缓存中是否已经存在该图片  
53.        if(caches.containsKey(path)){  
54.            // 取出软引用  
55.            SoftReference<Bitmap> rf = caches.get(path);  
56.            // 通过软引用,获取图片  
57.            Bitmap bitmap = rf.get();  
58.            // 如果该图片已经被释放,则将该path对应的键从Map中移除掉  
59.            if(bitmap == null){  
60.                caches.remove(path);  
61.            }else{  
62.                // 如果图片未被释放,直接返回该图片  
63.                Log.i(TAG, "return image in cache" + path);  
64.                return bitmap;  
65.            }  
66.        }else{  
67.            // 如果缓存中不常在该图片,则创建图片下载任务  
68.            Task task = new Task();  
69.            task.path = path;  
70.            task.callback = callback;  
71.            Log.i(TAG, "new Task ," + path);  
72.            if(!taskQueue.contains(task)){  
73.                taskQueue.add(task);  
74.                // 唤醒任务下载队列  
75.                synchronized (runnable) {  
76.                    runnable.notify();  
77.                }  
78.            }  
79.        }  
80.          
81.        // 缓存中没有图片则返回null  
82.        return null;  
83.    }  
84.      
85.    /** 
86.     *  
87.     * @param imageView  
88.     * @param resId 图片加载完成前显示的图片资源ID 
89.     * @return 
90.     */  
91.    private ImageCallback getImageCallback(final ImageView imageView, final int resId){  
92.        return new ImageCallback() {  
93.              
94.            @Override  
95.            public void loadImage(String path, Bitmap bitmap) {  
96.                if(path.equals(imageView.getTag().toString())){  
97.                    imageView.setImageBitmap(bitmap);  
98.                }else{  
99.                    imageView.setImageResource(resId);  
100.                }  
101.            }  
102.        };  
103.    }  
104.      
105.    private Handler handler = new Handler(){  
106.  
107.        @Override  
108.        public void handleMessage(Message msg) {  
109.            // 子线程中返回的下载完成的任务  
110.            Task task = (Task)msg.obj;  
111.            // 调用callback对象的loadImage方法,并将图片路径和图片回传给adapter  
112.            task.callback.loadImage(task.path, task.bitmap);  
113.        }  
114.          
115.    };  
116.      
117.    private Runnable runnable = new Runnable() {  
118.          
119.        @Override  
120.        public void run() {  
121.            while(isRunning){  
122.                // 当队列中还有未处理的任务时,执行下载任务  
123.                while(taskQueue.size() > 0){  
124.                    // 获取第一个任务,并将之从任务队列中删除  
125.                    Task task = taskQueue.remove(0);  
126.                    // 将下载的图片添加到缓存  
127.                    task.bitmap = PicUtil.getbitmap(task.path);  
128.                    caches.put(task.path, new SoftReference<Bitmap>(task.bitmap));  
129.                    if(handler != null){  
130.                        // 创建消息对象,并将完成的任务添加到消息对象中  
131.                        Message msg = handler.obtainMessage();  
132.                        msg.obj = task;  
133.                        // 发送消息回主线程  
134.                        handler.sendMessage(msg);  
135.                    }  
136.                }  
137.                  
138.                //如果队列为空,则令线程等待  
139.                synchronized (this) {  
140.                    try {  
141.                        this.wait();  
142.                    } catch (InterruptedException e) {  
143.                        e.printStackTrace();  
144.                    }  
145.                }  
146.            }  
147.        }  
148.    };  
149.      
150.    //回调接口  
151.    public interface ImageCallback{  
152.        void loadImage(String path, Bitmap bitmap);  
153.    }  
154.      
155.    class Task{  
156.        // 下载任务的下载路径  
157.        String path;  
158.        // 下载的图片  
159.        Bitmap bitmap;  
160.        // 回调对象  
161.        ImageCallback callback;  
162.          
163.        @Override  
164.        public boolean equals(Object o) {  
165.            Task task = (Task)o;  
166.            return task.path.equals(path);  
167.        }  
168.    }  
169.}  

最后附上PicUtil类的代码,之前忘了贴这个类的代码,不好意识了~~

01.public class PicUtil {  
02.    private static final String TAG = "PicUtil";  
03.  
04.    /** 
05.     * 根据一个网络连接(URL)获取bitmapDrawable图像 
06.     *  
07.     * @param imageUri 
08.     * @return 
09.     */  
10.    public static BitmapDrawable getfriendicon(URL imageUri) {  
11.  
12.        BitmapDrawable icon = null;  
13.        try {  
14.            HttpURLConnection hp = (HttpURLConnection) imageUri  
15.                    .openConnection();  
16.            icon = new BitmapDrawable(hp.getInputStream());// 将输入流转换成bitmap  
17.            hp.disconnect();// 关闭连接  
18.        } catch (Exception e) {  
19.        }  
20.        return icon;  
21.    }  
22.  
23.    /** 
24.     * 根据一个网络连接(String)获取bitmapDrawable图像 
25.     *  
26.     * @param imageUri 
27.     * @return 
28.     */  
29.    public static BitmapDrawable getcontentPic(String imageUri) {  
30.        URL imgUrl = null;  
31.        try {  
32.            imgUrl = new URL(imageUri);  
33.        } catch (MalformedURLException e1) {  
34.            e1.printStackTrace();  
35.        }  
36.        BitmapDrawable icon = null;  
37.        try {  
38.            HttpURLConnection hp = (HttpURLConnection) imgUrl.openConnection();  
39.            icon = new BitmapDrawable(hp.getInputStream());// 将输入流转换成bitmap  
40.            hp.disconnect();// 关闭连接  
41.        } catch (Exception e) {  
42.        }  
43.        return icon;  
44.    }  
45.  
46.    /** 
47.     * 根据一个网络连接(URL)获取bitmap图像 
48.     *  
49.     * @param imageUri 
50.     * @return 
51.     */  
52.    public static Bitmap getusericon(URL imageUri) {  
53.        // 显示网络上的图片  
54.        URL myFileUrl = imageUri;  
55.        Bitmap bitmap = null;  
56.        try {  
57.            HttpURLConnection conn = (HttpURLConnection) myFileUrl  
58.                    .openConnection();  
59.            conn.setDoInput(true);  
60.            conn.connect();  
61.            InputStream is = conn.getInputStream();  
62.            bitmap = BitmapFactory.decodeStream(is);  
63.            is.close();  
64.        } catch (IOException e) {  
65.            e.printStackTrace();  
66.        }  
67.        return bitmap;  
68.    }  
69.  
70.    /** 
71.     * 根据一个网络连接(String)获取bitmap图像 
72.     *  
73.     * @param imageUri 
74.     * @return 
75.     * @throws MalformedURLException 
76.     */  
77.    public static Bitmap getbitmap(String imageUri) {  
78.        // 显示网络上的图片  
79.        Bitmap bitmap = null;  
80.        try {  
81.            URL myFileUrl = new URL(imageUri);  
82.            HttpURLConnection conn = (HttpURLConnection) myFileUrl  
83.                    .openConnection();  
84.            conn.setDoInput(true);  
85.            conn.connect();  
86.            InputStream is = conn.getInputStream();  
87.            bitmap = BitmapFactory.decodeStream(is);  
88.            is.close();  
89.  
90.            Log.i(TAG, "image download finished." + imageUri);  
91.        } catch (IOException e) {  
92.            e.printStackTrace();  
93.            return null;  
94.        }  
95.        return bitmap;  
96.    }  
97.  
98.    /** 
99.     * 下载图片 同时写道本地缓存文件中 
100.     *  
101.     * @param context 
102.     * @param imageUri 
103.     * @return 
104.     * @throws MalformedURLException 
105.     */  
106.    public static Bitmap getbitmapAndwrite(String imageUri) {  
107.        Bitmap bitmap = null;  
108.        try {  
109.            // 显示网络上的图片  
110.            URL myFileUrl = new URL(imageUri);  
111.            HttpURLConnection conn = (HttpURLConnection) myFileUrl  
112.                    .openConnection();  
113.            conn.setDoInput(true);  
114.            conn.connect();  
115.  
116.            InputStream is = conn.getInputStream();  
117.            File cacheFile = FileUtil.getCacheFile(imageUri);  
118.            BufferedOutputStream bos = null;  
119.            bos = new BufferedOutputStream(new FileOutputStream(cacheFile));  
120.            Log.i(TAG, "write file to " + cacheFile.getCanonicalPath());  
121.  
122.            byte[] buf = new byte[1024];  
123.            int len = 0;  
124.            // 将网络上的图片存储到本地  
125.            while ((len = is.read(buf)) > 0) {  
126.                bos.write(buf, 0, len);  
127.            }  
128.  
129.            is.close();  
130.            bos.close();  
131.  
132.            // 从本地加载图片  
133.            bitmap = BitmapFactory.decodeFile(cacheFile.getCanonicalPath());  
134.            String name = MD5Util.MD5(imageUri);  
135.  
136.        } catch (IOException e) {  
137.            e.printStackTrace();  
138.        }  
139.        return bitmap;  
140.    }  
141.  
142.    public static boolean downpic(String picName, Bitmap bitmap) {  
143.        boolean nowbol = false;  
144.        try {  
145.            File saveFile = new File("/mnt/sdcard/download/weibopic/" + picName  
146.                    + ".png");  
147.            if (!saveFile.exists()) {  
148.                saveFile.createNewFile();  
149.            }  
150.            FileOutputStream saveFileOutputStream;  
151.            saveFileOutputStream = new FileOutputStream(saveFile);  
152.            nowbol = bitmap.compress(Bitmap.CompressFormat.PNG, 100,  
153.                    saveFileOutputStream);  
154.            saveFileOutputStream.close();  
155.        } catch (FileNotFoundException e) {  
156.            e.printStackTrace();  
157.        } catch (IOException e) {  
158.            e.printStackTrace();  
159.        } catch (Exception e) {  
160.            e.printStackTrace();  
161.        }  
162.        return nowbol;  
163.    }  
164.  
165.    public static void writeTofiles(Context context, Bitmap bitmap,  
166.            String filename) {  
167.        BufferedOutputStream outputStream = null;  
168.        try {  
169.            outputStream = new BufferedOutputStream(context.openFileOutput(  
170.                    filename, Context.MODE_PRIVATE));  
171.            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);  
172.        } catch (FileNotFoundException e) {  
173.            e.printStackTrace();  
174.        }  
175.    }  
176.  
177.    /** 
178.     * 将文件写入缓存系统中 
179.     *  
180.     * @param filename 
181.     * @param is 
182.     * @return 
183.     */  
184.    public static String writefile(Context context, String filename,  
185.            InputStream is) {  
186.        BufferedInputStream inputStream = null;  
187.        BufferedOutputStream outputStream = null;  
188.        try {  
189.            inputStream = new BufferedInputStream(is);  
190.            outputStream = new BufferedOutputStream(context.openFileOutput(  
191.                    filename, Context.MODE_PRIVATE));  
192.            byte[] buffer = new byte[1024];  
193.            int length;  
194.            while ((length = inputStream.read(buffer)) != -1) {  
195.                outputStream.write(buffer, 0, length);  
196.            }  
197.        } catch (Exception e) {  
198.        } finally {  
199.            if (inputStream != null) {  
200.                try {  
201.                    inputStream.close();  
202.                } catch (IOException e) {  
203.                    e.printStackTrace();  
204.                }  
205.            }  
206.            if (outputStream != null) {  
207.                try {  
208.                    outputStream.flush();  
209.                    outputStream.close();  
210.                } catch (IOException e) {  
211.                    e.printStackTrace();  
212.                }  
213.            }  
214.        }  
215.        return context.getFilesDir() + "/" + filename + ".jpg";  
216.    }  
217.  
218.    // 放大缩小图片  
219.    public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {  
220.        int width = bitmap.getWidth();  
221.        int height = bitmap.getHeight();  
222.        Matrix matrix = new Matrix();  
223.        float scaleWidht = ((float) w / width);  
224.        float scaleHeight = ((float) h / height);  
225.        matrix.postScale(scaleWidht, scaleHeight);  
226.        Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height,  
227.                matrix, true);  
228.        return newbmp;  
229.    }  
230.  
231.    // 将Drawable转化为Bitmap  
232.    public static Bitmap drawableToBitmap(Drawable drawable) {  
233.        int width = drawable.getIntrinsicWidth();  
234.        int height = drawable.getIntrinsicHeight();  
235.        Bitmap bitmap = Bitmap.createBitmap(width, height, drawable  
236.                .getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888  
237.                : Bitmap.Config.RGB_565);  
238.        Canvas canvas = new Canvas(bitmap);  
239.        drawable.setBounds(0, 0, width, height);  
240.        drawable.draw(canvas);  
241.        return bitmap;  
242.  
243.    }  
244.  
245.    // 获得圆角图片的方法  
246.    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {  
247.        if(bitmap == null){  
248.            return null;  
249.        }  
250.          
251.        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),  
252.                bitmap.getHeight(), Config.ARGB_8888);  
253.        Canvas canvas = new Canvas(output);  
254.  
255.        final int color = 0xff424242;  
256.        final Paint paint = new Paint();  
257.        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());  
258.        final RectF rectF = new RectF(rect);  
259.  
260.        paint.setAntiAlias(true);  
261.        canvas.drawARGB(0, 0, 0, 0);  
262.        paint.setColor(color);  
263.        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);  
264.  
265.        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
266.        canvas.drawBitmap(bitmap, rect, rect, paint);  
267.        return output;  
268.    }  
269.  
270.    // 获得带倒影的图片方法  
271.    public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {  
272.        final int reflectionGap = 4;  
273.        int width = bitmap.getWidth();  
274.        int height = bitmap.getHeight();  
275.  
276.        Matrix matrix = new Matrix();  
277.        matrix.preScale(1, -1);  
278.  
279.        Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,  
280.                width, height / 2, matrix, false);  
281.  
282.        Bitmap bitmapWithReflection = Bitmap.createBitmap(width,  
283.                (height + height / 2), Config.ARGB_8888);  
284.  
285.        Canvas canvas = new Canvas(bitmapWithReflection);  
286.        canvas.drawBitmap(bitmap, 0, 0, null);  
287.        Paint deafalutPaint = new Paint();  
288.        canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);  
289.  
290.        canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);  
291.  
292.        Paint paint = new Paint();  
293.        LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,  
294.                bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,  
295.                0x00ffffff, TileMode.CLAMP);  
296.        paint.setShader(shader);  
297.        // Set the Transfer mode to be porter duff and destination in  
298.        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  
299.        // Draw a rectangle using the paint with our linear gradient  
300.        canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()  
301.                + reflectionGap, paint);  
302.  
303.        return bitmapWithReflection;  
304.    }  
305.  
306.}  

 FileUtil

01.package com.wangge.coupon.util;  
02.  
03.import java.io.File;  
04.import java.io.IOException;  
05.  
06.import android.os.Environment;  
07.import android.util.Log;  
08.  
09.import com.wangge.coupon.http.AsynImageLoader;  
10.  
11.public class FileUtil {  
12.    private static final String TAG = "FileUtil";  
13.  
14.    public static File getCacheFile(String imageUri){  
15.        File cacheFile = null;  
16.        try {  
17.            if (Environment.getExternalStorageState().equals(  
18.                    Environment.MEDIA_MOUNTED)) {  
19.                File sdCardDir = Environment.getExternalStorageDirectory();  
20.                String fileName = getFileName(imageUri);  
21.                File dir = new File(sdCardDir.getCanonicalPath()  
22.                        + AsynImageLoader.CACHE_DIR);  
23.                if (!dir.exists()) {  
24.                    dir.mkdirs();  
25.                }  
26.                cacheFile = new File(dir, fileName);  
27.                Log.i(TAG, "exists:" + cacheFile.exists() + ",dir:" + dir + ",file:" + fileName);  
28.            }    
29.        } catch (IOException e) {  
30.            e.printStackTrace();  
31.            Log.e(TAG, "getCacheFileError:" + e.getMessage());  
32.        }  
33.          
34.        return cacheFile;  
35.    }  
36.      
37.    public static String getFileName(String path) {  
38.        int index = path.lastIndexOf("/");  
39.        return path.substring(index + 1);  
40.    }  
41.}  

 

posted @ 2015-08-10 11:50  涂文鼎  阅读(268)  评论(0编辑  收藏  举报