天天看點

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

異步加載圖檔的例子,網上也比較多,大部分用了hashmap<string, softreference<drawable>> imagecache ,但是現在已經不再推薦使用這種方式了,因為從 android 2.3 (api level 9)開始,垃圾回收器會更傾向于回收持有軟引用或弱引用的對象,這讓軟引用和弱引用變得不再可靠。另外,android 3.0 (api level 11)中,圖檔的資料會存儲在本地的記憶體當中,因而無法用一種可預見的方式将其釋放,這就有潛在的風險造成應用程式的記憶體溢出并崩潰,是以我這裡用得是lrucache來緩存圖檔,當存儲image的大小大于lrucache設定的值,系統自動釋放記憶體,這個類是3.1版本中提供的,如果你是在更早的android版本中開發,則需要導入android-support-v4的jar包(這裡要注意咯)

為什麼寫這篇文章呢?

這篇文章做了哪些方面的優化

使用了線程池來管理下載下傳任務

使用lrucache來緩存圖檔

使用手機來緩存圖檔

gridview滑動的時候取消下載下傳任務,靜止的時候進行下載下傳,gridview滑動更加的流暢

降低了代碼的耦合性,結構更加的清晰,便于以後重用

接下來我們先來看看項目的結構

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

fileutils 檔案操作的工具類,提供儲存圖檔,擷取圖檔,判斷圖檔是否存在,删除圖檔的一些方法,這個類比較簡單

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

package com.example.asyncimageloader;  

import java.io.file;  

import java.io.fileoutputstream;  

import java.io.ioexception;  

import android.content.context;  

import android.graphics.bitmap;  

import android.graphics.bitmap.compressformat;  

import android.graphics.bitmapfactory;  

import android.os.environment;  

public class fileutils {  

    /** 

     * sd卡的根目錄 

     */  

    private static string msdrootpath = environment.getexternalstoragedirectory().getpath();  

     * 手機的緩存根目錄 

    private static string mdatarootpath = null;  

     * 儲存image的目錄名 

    private final static string folder_name = "/androidimage";  

    public fileutils(context context){  

        mdatarootpath = context.getcachedir().getpath();  

    }  

     * 擷取儲存image的目錄 

     * @return 

    private string getstoragedirectory(){  

        return environment.getexternalstoragestate().equals(environment.media_mounted) ?  

                msdrootpath + folder_name : mdatarootpath + folder_name;  

     * 儲存image的方法,有sd卡存儲到sd卡,沒有就存儲到手機目錄 

     * @param filename  

     * @param bitmap    

     * @throws ioexception 

    public void savabitmap(string filename, bitmap bitmap) throws ioexception{  

        if(bitmap == null){  

            return;  

        }  

        string path = getstoragedirectory();  

        file folderfile = new file(path);  

        if(!folderfile.exists()){  

            folderfile.mkdir();  

        file file = new file(path + file.separator + filename);  

        file.createnewfile();  

        fileoutputstream fos = new fileoutputstream(file);  

        bitmap.compress(compressformat.jpeg, 100, fos);  

        fos.flush();  

        fos.close();  

     * 從手機或者sd卡擷取bitmap 

     * @param filename 

    public bitmap getbitmap(string filename){  

        return bitmapfactory.decodefile(getstoragedirectory() + file.separator + filename);  

     * 判斷檔案是否存在 

    public boolean isfileexists(string filename){  

        return new file(getstoragedirectory() + file.separator + filename).exists();  

     * 擷取檔案的大小 

    public long getfilesize(string filename) {  

        return new file(getstoragedirectory() + file.separator + filename).length();  

     * 删除sd卡或者手機的緩存圖檔和目錄 

    public void deletefile() {  

        file dirfile = new file(getstoragedirectory());  

        if(! dirfile.exists()){  

        if (dirfile.isdirectory()) {  

            string[] children = dirfile.list();  

            for (int i = 0; i < children.length; i++) {  

                new file(dirfile, children[i]).delete();  

            }  

        dirfile.delete();  

}<span style="font-family:times new roman;font-size:14px;">  

</span>  

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

public class images {  

    public final static string[] imagethumburls = new string[] {  

            "https://lh6.googleusercontent.com/-55osaww3x0q/urquutcfr5i/aaaaaaaaabs/rwlj1rukryi/s160-c/a%252520photographer.jpg",  

            "https://lh4.googleusercontent.com/--dq8nirp7w4/urquvgmxvgi/aaaaaaaaabs/-gnulqfnnba/s160-c/a%252520song%252520of%252520ice%252520and%252520fire.jpg",  

            "https://lh5.googleusercontent.com/-7qzedtrkfkc/urquwzt1goi/aaaaaaaaabs/hqwgteynxsg/s160-c/another%252520rockaway%252520sunset.jpg",  

            "https://lh3.googleusercontent.com/--l0km39l5j8/urquxhgcdni/aaaaaaaaabs/3zrsjnrsomq/s160-c/antelope%252520butte.jpg",  

            "https://lh6.googleusercontent.com/-8ho-4vifnlw/urquznsfgti/aaaaaaaaabs/wt8jvitf7vw/s160-c/antelope%252520hallway.jpg",  

            "https://lh4.googleusercontent.com/-wiuwgvcu3qw/urqubrvcj4i/aaaaaaaaabs/yvbwggjwdiq/s160-c/antelope%252520walls.jpg",  

            "https://lh6.googleusercontent.com/-ubmlbpelvoq/urquccdv0ki/aaaaaaaaabs/idnhr2vqoqs/s160-c/apre%2525cc%252580s%252520la%252520pluie.jpg",  

            "https://lh3.googleusercontent.com/-s-afpvgseew/urquc6df-ji/aaaaaaaaabs/mt3xngrud68/s160-c/backlit%252520cloud.jpg",  

            "https://lh5.googleusercontent.com/-bvmif9a9yoq/urquea3hehi/aaaaaaaaabs/rcr6wyeqtao/s160-c/bee%252520and%252520flower.jpg",  

            "https://lh5.googleusercontent.com/-n7mdm7i7fgs/urquet_bt-i/aaaaaaaaabs/9mymxlmpsao/s160-c/bonzai%252520rock%252520sunset.jpg",  

            "https://lh6.googleusercontent.com/-4cn4x4t0m1k/urqufpozwzi/aaaaaaaaabs/8wk41lg1kps/s160-c/caterpillar.jpg",  

            "https://lh3.googleusercontent.com/-rrfnvc8xqeg/urqufdrlbai/aaaaaaaaabs/s69wyy_fl1e/s160-c/chess.jpg",  

            "https://lh5.googleusercontent.com/-wvprptwh8yw/urqugh-qmdi/aaaaaaaaabs/e-mgbgtluwu/s160-c/chihuly.jpg",  

            "https://lh5.googleusercontent.com/-0bdxkymckbo/urquhkfw84i/aaaaaaaaabs/ogqthctk2jq/s160-c/closed%252520door.jpg",  

            "https://lh3.googleusercontent.com/-pyggxxzrykm/urquh-kvvoi/aaaaaaaaabs/hftdwhtrhhq/s160-c/colorado%252520river%252520sunset.jpg",  

            "https://lh3.googleusercontent.com/-zas4dnztalc/urquikvocwi/aaaaaaaaabs/dxz4h3dll1y/s160-c/colors%252520of%252520autumn.jpg",  

            "https://lh4.googleusercontent.com/-gztnweiimz8/urqukvcu7bi/aaaaaaaaabs/jo2hjv6mz6m/s160-c/countryside.jpg",  

            "https://lh4.googleusercontent.com/-beg9ez9qoim/urquklz3fgi/aaaaaaaaabs/uuuv8ac2bae/s160-c/death%252520valley%252520-%252520dunes.jpg",  

            "https://lh6.googleusercontent.com/-ijqj8w68tee/urqulgkvfei/aaaaaaaaabs/zpxviwi_rfw/s160-c/delicate%252520arch.jpg",  

            "https://lh5.googleusercontent.com/-oh8mmy2ieng/urqulldwehi/aaaaaaaaabs/tbdeefsaizy/s160-c/despair.jpg",  

            "https://lh5.googleusercontent.com/-gl0y4uiaolk/urqumc_kjbi/aaaaaaaaabs/pm1et7dn4oo/s160-c/eagle%252520fall%252520sunrise.jpg",  

            "https://lh3.googleusercontent.com/-hyyhd2_vxpq/urqumtja9ei/aaaaaaaaabs/waalxvkbsh0/s160-c/electric%252520storm.jpg",  

            "https://lh5.googleusercontent.com/-pyy_yiyjpto/urqunuohhfi/aaaaaaaaabs/azzoulnujxc/s160-c/false%252520kiva.jpg",  

            "https://lh6.googleusercontent.com/-pyvlvdvxywk/urqunwd8hfi/aaaaaaaaabs/qimwgkfvf6i/s160-c/fitzgerald%252520streaks.jpg",  

            "https://lh4.googleusercontent.com/-kir_uobiiqy/urquocz9sli/aaaaaaaaabs/y4d4q8sxu4c/s160-c/foggy%252520sunset.jpg",  

            "https://lh6.googleusercontent.com/-9lzok_owzh0/urquoo4xyoi/aaaaaaaaabs/awgzhtnvcwu/s160-c/frantic.jpg",  

            "https://lh3.googleusercontent.com/-0x3jnakaz48/urquph78wpi/aaaaaaaaabs/lhxxu_zbh8s/s160-c/golden%252520gate%252520afternoon.jpg",  

            "https://lh6.googleusercontent.com/-95sb5ag7abc/urqupl95rdi/aaaaaaaaabs/g73r20ivtra/s160-c/golden%252520gate%252520fog.jpg",  

            "https://lh3.googleusercontent.com/-jb9v6rtghhk/urqup21f-zi/aaaaaaaaabs/64fb8qmzwxk/s160-c/golden%252520grass.jpg",  

            "https://lh4.googleusercontent.com/-eibgfnultii/urquqvhwari/aaaaaaaaabs/fa4mcv2u8ve/s160-c/grand%252520teton.jpg",  

            "https://lh4.googleusercontent.com/-womxzvmn9ny/urquq1v2aoi/aaaaaaaaabs/grj5umhl6na/s160-c/grass%252520closeup.jpg",  

            "https://lh3.googleusercontent.com/-6hziehxx64q/urqurxvndqi/aaaaaaaaabs/kwmxm3o5ovi/s160-c/green%252520grass.jpg",  

            "https://lh5.googleusercontent.com/-6lvb9oxtq60/urqutebfuki/aaaaaaaaabs/4f4krgecwfs/s160-c/hanging%252520leaf.jpg",  

            "https://lh4.googleusercontent.com/-zavf__52onk/urqutt_iuxi/aaaaaaaaabs/d_bcuc0thou/s160-c/highway%2525201.jpg",  

            "https://lh6.googleusercontent.com/-h4srug615ra/urquul27fxi/aaaaaaaaabs/4aeqjfimsou/s160-c/horseshoe%252520bend%252520sunset.jpg",  

            "https://lh4.googleusercontent.com/-jhfi4fb_pqw/urquux-qxbi/aaaaaaaaabs/ixpyuxuweym/s160-c/horseshoe%252520bend.jpg",  

            "https://lh5.googleusercontent.com/-uggssvfrj7g/urquueyjzgi/aaaaaaaaabs/yyibllt0tom/s160-c/into%252520the%252520blue.jpg",  

            "https://lh3.googleusercontent.com/-ch7koupi7ui/urquu0ff__i/aaaaaaaaabs/r7gdmi7v_g0/s160-c/jelly%252520fish%2525202.jpg",  

            "https://lh4.googleusercontent.com/-pwuuw6yhg8u/urquvpxr3fi/aaaaaaaaabs/vngk6f-tsge/s160-c/jelly%252520fish%2525203.jpg",  

            "https://lh5.googleusercontent.com/-gouqvw1fnfw/urquv6xbc0i/aaaaaaaaabs/zeuvtqq43zc/s160-c/kauai.jpg",  

            "https://lh6.googleusercontent.com/-8qdyyqepyjw/urquwvdh88i/aaaaaaaaabs/cktdy-ysfho/s160-c/kyoto%252520sunset.jpg",  

            "https://lh4.googleusercontent.com/-vpeekydjoe0/urquwzj28qi/aaaaaaaaabs/qxcyxulszrg/s160-c/lake%252520tahoe%252520colors.jpg",  

            "https://lh4.googleusercontent.com/-xbpxwpd4yxu/urquxwhk8ai/aaaaaaaaabs/ardpedypimy/s160-c/lava%252520from%252520the%252520sky.jpg",  

            "https://lh3.googleusercontent.com/-897vxrjb6re/urquxxxd-5i/aaaaaaaaabs/j-cz4t4yviw/s160-c/leica%25252050mm%252520summilux.jpg",  

            "https://lh5.googleusercontent.com/-qsj4d4ixzgo/urquydwij1i/aaaaaaaaabs/k2pbxewehoa/s160-c/leica%25252050mm%252520summilux.jpg",  

            "https://lh6.googleusercontent.com/-dwlpg83vzlg/urquyltvufi/aaaaaaaaabs/g6syq8b4ysi/s160-c/leica%252520m8%252520%252528front%252529.jpg",  

            "https://lh3.googleusercontent.com/-r3_eyayjvfk/urquzqbv8ei/aaaaaaaaabs/b9xhpum3pei/s160-c/light%252520to%252520sand.jpg",  

            "https://lh3.googleusercontent.com/-fhy5h67qpi0/urqu0cp4j1i/aaaaaaaaabs/0lg6m94z6vm/s160-c/little%252520bit%252520of%252520paradise.jpg",  

            "https://lh5.googleusercontent.com/-tzf_lwrcnrm/urqu0rddpoi/aaaaaaaaabs/gaj2dliux0s/s160-c/lone%252520pine%252520sunset.jpg",  

            "https://lh3.googleusercontent.com/-4hdpj4_dxu4/urqu046dj9i/aaaaaaaaabs/eboodtk2_uk/s160-c/lonely%252520rock.jpg",  

            "https://lh6.googleusercontent.com/-erbf--z-w4s/urqu1ajslki/aaaaaaaaabs/xjdcdo1inzm/s160-c/longue%252520vue.jpg",  

            "https://lh6.googleusercontent.com/-0cxjrdjaqvc/urqu1opnzni/aaaaaaaaabs/pfb2opuu7lk/s160-c/look%252520me%252520in%252520the%252520eye.jpg",  

            "https://lh3.googleusercontent.com/-d_5lnxndn6g/urqu2tk7hvi/aaaaaaaaabs/p0ddca9w__y/s160-c/lost%252520in%252520a%252520field.jpg",  

            "https://lh6.googleusercontent.com/-flsqwmrik2q/urqu24pcmji/aaaaaaaaabs/5ocih85xofm/s160-c/marshall%252520beach%252520sunset.jpg",  

            "https://lh4.googleusercontent.com/-y4lgryevtmu/urqu28kg3gi/aaaaaaaaabs/ojxpekqtbj4/s160-c/mono%252520lake%252520blue.jpg",  

            "https://lh4.googleusercontent.com/-aahajpmcgya/urqu3pildhi/aaaaaaaaabs/lctqk1sicrs/s160-c/monument%252520valley%252520overlook.jpg",  

            "https://lh4.googleusercontent.com/-vkxfdq83dqa/urqu31yq_bi/aaaaaaaaabs/ouogk_2ayfm/s160-c/moving%252520rock.jpg",  

            "https://lh5.googleusercontent.com/-cg62qippwxg/urqu4ia4vri/aaaaaaaaabs/0yodqlalcac/s160-c/napali%252520coast.jpg",  

            "https://lh6.googleusercontent.com/-wdgrp5pmmjq/urqu5pzvn7i/aaaaaaaaabs/m0abecdpxe4/s160-c/one%252520wheel.jpg",  

            "https://lh6.googleusercontent.com/-6ws5docguoa/urqu5qx1ugi/aaaaaaaaabs/gimw2ixpvry/s160-c/open%252520sky.jpg",  

            "https://lh6.googleusercontent.com/-u8ehkj8g8gq/urqu55sm6yi/aaaaaaaaabs/lixx_gltdmi/s160-c/orange%252520sunset.jpg",  

            "https://lh6.googleusercontent.com/-74z5qj4btde/urqu6lsrjri/aaaaaaaaabs/xzmvkw90szq/s160-c/orchid.jpg",  

            "https://lh6.googleusercontent.com/-leqe4h6tepe/urqu6t_lski/aaaaaaaaabs/zvgykoea_qy/s160-c/over%252520there.jpg",  

            "https://lh5.googleusercontent.com/-cauh-53jh2m/urqu66v_usi/aaaaaaaaabs/eucwwqclfkq/s160-c/plumes.jpg",  

            "https://lh3.googleusercontent.com/-edlt2jhdoy4/urqu7axzkai/aaaaaaaaabs/ivze-xj7lzs/s160-c/rainbokeh.jpg",  

            "https://lh5.googleusercontent.com/-j1nlqefiyco/urqu8l1cgci/aaaaaaaaabs/aqzkgx66zli/s160-c/rainbow.jpg",  

            "https://lh5.googleusercontent.com/-drnqmk0t4vu/urqu8xyn9yi/aaaaaaaaabs/lgvf_592wlu/s160-c/rice%252520fields.jpg",  

            "https://lh3.googleusercontent.com/-hwh1v3eogcq/urqu8qoakwi/aaaaaaaaabs/iljrjrnbjgw/s160-c/rockaway%252520fire%252520sky.jpg",  

            "https://lh5.googleusercontent.com/-wjv6fqk7tlk/urqu9jcq8si/aaaaaaaaabs/ryyupdo-c9o/s160-c/rockaway%252520flow.jpg",  

            "https://lh6.googleusercontent.com/-6caxnfo7d20/urqu-bdzgpi/aaaaaaaaabs/omsyllzjqwo/s160-c/rockaway%252520sunset%252520sky.jpg",  

            "https://lh3.googleusercontent.com/-sl8fpgps-re/urqu_bokfgi/aaaaaaaaabs/dg2fv-jxoeg/s160-c/russian%252520ridge%252520sunset.jpg",  

            "https://lh6.googleusercontent.com/-gvty36mmbig/urqu_q91lki/aaaaaaaaabs/3cifmbcy5ma/s160-c/rust%252520knot.jpg",  

            "https://lh6.googleusercontent.com/-gheimuhqjbe/urqu_fkfvli/aaaaaaaaabs/axuejeqam7q/s160-c/sailing%252520stones.jpg",  

            "https://lh3.googleusercontent.com/-hbbyzjtowgc/urqu_ycpiri/aaaaaaaaabs/nadjuxngjye/s160-c/seahorse.jpg",  

            "https://lh3.googleusercontent.com/-iwi6-i6iexy/urqvayzhsvi/aaaaaaaaabs/5etwl4qxsfe/s160-c/shinjuku%252520street.jpg",  

            "https://lh6.googleusercontent.com/-amhnystm_my/urqvalb5koi/aaaaaaaaabs/pfcfgzlksn0/s160-c/sierra%252520heavens.jpg",  

            "https://lh5.googleusercontent.com/-djgjepfryso/urqvbvjzrai/aaaaaaaaabs/v-f5qwpyo6s/s160-c/sierra%252520sunset.jpg",  

            "https://lh4.googleusercontent.com/-z4zgic5nwdc/urqvbdewivi/aaaaaaaaabs/zrzr1vj84qa/s160-c/sin%252520lights.jpg",  

            "https://lh4.googleusercontent.com/-_0cyiww8ccy/urqvbz3im4i/aaaaaaaaabs/9n_wq8mhlty/s160-c/starry%252520lake.jpg",  

            "https://lh3.googleusercontent.com/-a9lmoryuqua/urqvcyx_joi/aaaaaaaaabs/s7sde1bz9ci/s160-c/starry%252520night.jpg",  

            "https://lh3.googleusercontent.com/-ktlj3k858ey/urqvc_2h_bi/aaaaaaaaabs/zzebimwda_g/s160-c/stream.jpg",  

            "https://lh5.googleusercontent.com/-dfb7lad6rca/urqvduftwwi/aaaaaaaaabs/brhoutxtn7o/s160-c/strip%252520sunset.jpg",  

            "https://lh5.googleusercontent.com/-at6apgfin20/urqvdyffuzi/aaaaaaaaabs/clabcx171be/s160-c/sunset%252520hills.jpg",  

            "https://lh4.googleusercontent.com/-7-ehhtqthii/urqveytk4vi/aaaaaaaaabs/qsjzob3yjvg/s160-c/tenaya%252520lake%2525202.jpg",  

            "https://lh6.googleusercontent.com/-8mrjv_a-pok/urqvfc5repi/aaaaaaaaabs/9inktg9fbce/s160-c/tenaya%252520lake.jpg",  

            "https://lh5.googleusercontent.com/-b1hw-z4zwao/urqvfwyrwui/aaaaaaaaabs/8peli53bs8i/s160-c/the%252520cave%252520bw.jpg",  

            "https://lh3.googleusercontent.com/-po4e-xzkanq/urqvgrqjyki/aaaaaaaaabs/42nyadfsxag/s160-c/the%252520fisherman.jpg",  

            "https://lh4.googleusercontent.com/-ilyzlzfdy7s/urqvg0yscdi/aaaaaaaaabs/1j9edkmkxtk/s160-c/the%252520night%252520is%252520coming.jpg",  

            "https://lh6.googleusercontent.com/-g-k7ykkuco0/urqvhhah6fi/aaaaaaaaabs/_taqqg7t0vo/s160-c/the%252520road.jpg",  

            "https://lh6.googleusercontent.com/-h-aljt7ksus/urqvithqyfi/aaaaaaaaabs/ejiv35olws8/s160-c/tokyo%252520heights.jpg",  

            "https://lh5.googleusercontent.com/-hy9k-tbs7xg/urqvijqmoxi/aaaaaaaaabs/rspmmoatskg/s160-c/tokyo%252520highway.jpg",  

            "https://lh6.googleusercontent.com/-83oovmb4ozs/urqvjl0t7li/aaaaaaaaabs/c5tecz6ronm/s160-c/tokyo%252520smog.jpg",  

            "https://lh3.googleusercontent.com/-fb-jfgreefi/urqvji3exai/aaaaaaaaabs/xfyweirf4v8/s160-c/tufa%252520at%252520night.jpg",  

            "https://lh4.googleusercontent.com/-vngkd5z1u8w/urqvjucegpi/aaaaaaaaabs/ulxcmvcu6eu/s160-c/valley%252520sunset.jpg",  

            "https://lh6.googleusercontent.com/-doz5i2e2omq/urqvkmnd1ki/aaaaaaaaabs/iqf0isinleo/s160-c/windmill%252520sunrise.jpg",  

            "https://lh5.googleusercontent.com/-biyiywcj9mu/urqvkculiai/aaaaaaaaabs/jypscpljope/s160-c/windmill.jpg",  

            "https://lh4.googleusercontent.com/-pdt167_xrda/urqvk36mlci/aaaaaaaaabs/oi2ik9qsemi/s160-c/windmills.jpg",  

            "https://lh5.googleusercontent.com/-ki_qdyx7vlu/urqvlxcb6gi/aaaaaaaaabs/n31vlz6u89o/s160-c/yet%252520another%252520rockaway%252520sunset.jpg",  

            "https://lh4.googleusercontent.com/-e9nhz5k5mss/urqvmibzjti/aaaaaaaaabs/1fv810rdnfq/s160-c/yosemite%252520tree.jpg", };  

imagedownloader類,異步下載下傳的核心類,儲存圖檔到手機緩存,将圖檔加入lrucache中等等

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

import java.net.httpurlconnection;  

import java.net.url;  

import java.util.concurrent.executorservice;  

import java.util.concurrent.executors;  

import android.os.handler;  

import android.os.message;  

import android.support.v4.util.lrucache;  

public class imagedownloader {  

     * 緩存image的類,當存儲image的大小大于lrucache設定的值,系統自動釋放記憶體 

    private lrucache<string, bitmap> mmemorycache;  

     * 操作檔案相關類對象的引用 

    private fileutils fileutils;  

     * 下載下傳image的線程池 

    private executorservice mimagethreadpool = null;  

    public imagedownloader(context context){  

        //擷取系統配置設定給每個應用程式的最大記憶體,每個應用系統配置設定32m  

        int maxmemory = (int) runtime.getruntime().maxmemory();    

        int mcachesize = maxmemory / 8;  

        //給lrucache配置設定1/8 4m  

        mmemorycache = new lrucache<string, bitmap>(mcachesize){  

            //必須重寫此方法,來測量bitmap的大小  

            @override  

            protected int sizeof(string key, bitmap value) {  

                return value.getrowbytes() * value.getheight();  

        };  

        fileutils = new fileutils(context);  

     * 擷取線程池的方法,因為涉及到并發的問題,我們加上同步鎖 

    public executorservice getthreadpool(){  

        if(mimagethreadpool == null){  

            synchronized(executorservice.class){  

                if(mimagethreadpool == null){  

                    //為了下載下傳圖檔更加的流暢,我們用了2個線程來下載下傳圖檔  

                    mimagethreadpool = executors.newfixedthreadpool(2);  

                }  

        return mimagethreadpool;  

     * 添加bitmap到記憶體緩存 

     * @param key 

     * @param bitmap 

    public void addbitmaptomemorycache(string key, bitmap bitmap) {    

        if (getbitmapfrommemcache(key) == null && bitmap != null) {    

            mmemorycache.put(key, bitmap);    

        }    

    }    

     * 從記憶體緩存中擷取一個bitmap 

    public bitmap getbitmapfrommemcache(string key) {    

        return mmemorycache.get(key);    

    }   

     * 先從記憶體緩存中擷取bitmap,如果沒有就從sd卡或者手機緩存中擷取,sd卡或者手機緩存 

     * 沒有就去下載下傳 

     * @param url 

     * @param listener 

    public bitmap downloadimage(final string url, final onimageloaderlistener listener){  

        //替換url中非字母和非數字的字元,這裡比較重要,因為我們用url作為檔案名,比如我們的url  

        //是http://xiaanming/abc.jpg;用這個作為圖檔名稱,系統會認為xiaanming為一個目錄,  

        //我們沒有建立此目錄儲存檔案就會報錯  

        final string suburl = url.replaceall("[^\\w]", "");  

        bitmap bitmap = showcachebitmap(suburl);  

        if(bitmap != null){  

            return bitmap;  

        }else{  

            final handler handler = new handler(){  

                @override  

                public void handlemessage(message msg) {  

                    super.handlemessage(msg);  

                    listener.onimageloader((bitmap)msg.obj, url);  

            };  

            getthreadpool().execute(new runnable() {  

                public void run() {  

                    bitmap bitmap = getbitmapformurl(url);  

                    message msg = handler.obtainmessage();  

                    msg.obj = bitmap;  

                    handler.sendmessage(msg);  

                    try {  

                        //儲存在sd卡或者手機目錄  

                        fileutils.savabitmap(suburl, bitmap);  

                    } catch (ioexception e) {  

                        e.printstacktrace();  

                    }  

                    //将bitmap 加入記憶體緩存  

                    addbitmaptomemorycache(suburl, bitmap);  

            });  

        return null;  

     * 擷取bitmap, 記憶體中沒有就去手機或者sd卡中擷取,這一步在getview中會調用,比較關鍵的一步 

    public bitmap showcachebitmap(string url){  

        if(getbitmapfrommemcache(url) != null){  

            return getbitmapfrommemcache(url);  

        }else if(fileutils.isfileexists(url) && fileutils.getfilesize(url) != 0){  

            //從sd卡擷取手機裡面擷取bitmap  

            bitmap bitmap = fileutils.getbitmap(url);  

            //将bitmap 加入記憶體緩存  

            addbitmaptomemorycache(url, bitmap);  

     * 從url中擷取bitmap 

    private bitmap getbitmapformurl(string url) {  

        bitmap bitmap = null;  

        httpurlconnection con = null;  

        try {  

            url mimageurl = new url(url);  

            con = (httpurlconnection) mimageurl.openconnection();  

            con.setconnecttimeout(10 * 1000);  

            con.setreadtimeout(10 * 1000);  

            con.setdoinput(true);  

            con.setdooutput(true);  

            bitmap = bitmapfactory.decodestream(con.getinputstream());  

        } catch (exception e) {  

            e.printstacktrace();  

        } finally {  

            if (con != null) {  

                con.disconnect();  

        return bitmap;  

     * 取消正在下載下傳的任務 

    public synchronized void canceltask() {  

        if(mimagethreadpool != null){  

            mimagethreadpool.shutdownnow();  

            mimagethreadpool = null;  

     * 異步下載下傳圖檔的回調接口 

     * @author len 

     * 

    public interface onimageloaderlistener{  

        void onimageloader(bitmap bitmap, string url);  

}  

imagedownloader中有幾個方法比較重要

首先我們需要重寫sizeof(string key, bitmap value)來計算圖檔的大小,預設傳回圖檔的數量

downloadimage(final string url, final onimageloaderlistener listener)先去lrucache檢視image,沒有再去手機緩存中檢視,在沒有則開啟線程下載下傳,這裡我們提供了一個回調接口,回調方法中我們将bitmap和圖檔url作為參數,string suburl = url.replaceall("[^\\w]", "") 我在代碼中注釋寫的比較清楚

showcachebitmap(string url)方法,此方法在adapter中的getview()當中調用,如果getview()中不調用此方法試試你就知道效果了

imageadapter  gridview的擴充卡類,主要是gridview滑動的時候取消下載下傳任務,靜止的時候去下載下傳目前顯示的item的圖檔,其他也沒什麼不同了

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

import android.view.view;  

import android.view.viewgroup;  

import android.widget.abslistview;  

import android.widget.abslistview.onscrolllistener;  

import android.widget.baseadapter;  

import android.widget.gridview;  

import android.widget.imageview;  

import com.example.asyncimageloader.imagedownloader.onimageloaderlistener;  

public class imageadapter extends baseadapter implements onscrolllistener{  

     * 上下文對象的引用 

    private context context;  

     * image url的數組 

    private string [] imagethumburls;  

     * gridview對象的應用 

    private gridview mgridview;  

     * image 下載下傳器 

    private imagedownloader mimagedownloader;  

     * 記錄是否剛打開程式,用于解決進入程式不滾動螢幕,不會下載下傳圖檔的問題。 

     * 參考http://blog.csdn.net/guolin_blog/article/details/9526203#comments 

    private boolean isfirstenter = true;  

     * 一屏中第一個item的位置 

    private int mfirstvisibleitem;  

     * 一屏中所有item的個數 

    private int mvisibleitemcount;  

    public imageadapter(context context, gridview mgridview, string [] imagethumburls){  

        this.context = context;  

        this.mgridview = mgridview;  

        this.imagethumburls = imagethumburls;  

        mimagedownloader = new imagedownloader(context);  

        mgridview.setonscrolllistener(this);  

    @override  

    public void onscrollstatechanged(abslistview view, int scrollstate) {  

        //僅當gridview靜止時才去下載下傳圖檔,gridview滑動時取消所有正在下載下傳的任務    

        if(scrollstate == abslistview.onscrolllistener.scroll_state_idle){  

            showimage(mfirstvisibleitem, mvisibleitemcount);  

            canceltask();  

     * gridview滾動的時候調用的方法,剛開始顯示gridview也會調用此方法 

    public void onscroll(abslistview view, int firstvisibleitem,  

            int visibleitemcount, int totalitemcount) {  

        mfirstvisibleitem = firstvisibleitem;  

        mvisibleitemcount = visibleitemcount;  

        // 是以在這裡為首次進入程式開啟下載下傳任務。   

        if(isfirstenter && visibleitemcount > 0){  

            isfirstenter = false;  

    public int getcount() {  

        return imagethumburls.length;  

    public object getitem(int position) {  

        return imagethumburls[position];  

    public long getitemid(int position) {  

        return position;  

    public view getview(int position, view convertview, viewgroup parent) {  

        imageview mimageview;  

        final string mimageurl = imagethumburls[position];  

        if(convertview == null){  

            mimageview = new imageview(context);  

            mimageview = (imageview) convertview;  

        mimageview.setlayoutparams(new gridview.layoutparams(150, 150));  

        mimageview.setscaletype(imageview.scaletype.center_inside);  

        //給imageview設定tag,這裡已經是司空見慣了  

        mimageview.settag(mimageurl);  

        /*******************************去掉下面這幾行試試是什麼效果****************************/  

        bitmap bitmap = mimagedownloader.showcachebitmap(mimageurl.replaceall("[^\\w]", ""));  

            mimageview.setimagebitmap(bitmap);  

            mimageview.setimagedrawable(context.getresources().getdrawable(r.drawable.ic_empty));  

        /**********************************************************************************/  

        return mimageview;  

     * 顯示目前螢幕的圖檔,先會去查找lrucache,lrucache沒有就去sd卡或者手機目錄查找,在沒有就開啟線程去下載下傳 

     * @param firstvisibleitem 

     * @param visibleitemcount 

    private void showimage(int firstvisibleitem, int visibleitemcount){  

        for(int i=firstvisibleitem; i<firstvisibleitem + visibleitemcount; i++){  

            string mimageurl = imagethumburls[i];  

            final imageview mimageview = (imageview) mgridview.findviewwithtag(mimageurl);  

            bitmap = mimagedownloader.downloadimage(mimageurl, new onimageloaderlistener() {  

                public void onimageloader(bitmap bitmap, string url) {  

                    if(mimageview != null && bitmap != null){  

                        mimageview.setimagebitmap(bitmap);  

            //if(bitmap != null){  

            //  mimageview.setimagebitmap(bitmap);  

            //}else{  

            //  mimageview.setimagedrawable(context.getresources().getdrawable(r.drawable.ic_empty));  

            //}  

     * 取消下載下傳任務 

    public void canceltask(){  

        mimagedownloader.canceltask();  

mainactivity  裡面一個gridview,然後提供一個系統菜單來删除手機上的緩存圖檔,直接上代碼,比較簡單是以裡面也沒有注釋

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

import android.app.activity;  

import android.os.bundle;  

import android.view.menu;  

import android.view.menuitem;  

import android.widget.toast;  

public class mainactivity extends activity {  

    private string [] imagethumburls = images.imagethumburls;   

    private imageadapter mimageadapter;  

    protected void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        setcontentview(r.layout.activity_main);  

        fileutils = new fileutils(this);  

        mgridview = (gridview) findviewbyid(r.id.gridview);  

        mimageadapter = new imageadapter(this, mgridview, imagethumburls);  

        mgridview.setadapter(mimageadapter);  

    protected void ondestroy() {  

        mimageadapter.canceltask();  

        super.ondestroy();  

    public boolean oncreateoptionsmenu(menu menu) {  

        super.oncreateoptionsmenu(menu);  

        menu.add("删除手機中圖檔緩存");  

        return super.oncreateoptionsmenu(menu);  

    public boolean onoptionsitemselected(menuitem item) {  

        switch (item.getitemid()) {  

        case 0:  

            fileutils.deletefile();  

            toast.maketext(getapplication(), "清空緩存成功", toast.length_short).show();  

            break;  

        return super.onoptionsitemselected(item);  

mainactivity的布局檔案

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

    android:layout_width="match_parent"  

    android:layout_height="match_parent"  

    tools:context=".mainactivity" >  

    <gridview  

        android:id="@+id/gridview"  

        android:layout_width="match_parent"  

        android:layout_height="match_parent"  

        android:stretchmode="columnwidth"   

        android:columnwidth="90dip"   

        android:verticalspacing="10dip"  

        android:horizontalspacing="10dip"  

        android:cachecolorhint="@android:color/transparent"  

        android:numcolumns="auto_fit" >  

    </gridview>  

</relativelayout>  

因為有網絡操作和對sd卡的操作,是以我們必須加上相對應的權限

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

<uses-permission android:name="android.permission.internet" />   

<uses-permission android:name="android.permission.write_external_storage" />   

好了,代碼就全部介紹完了,我們運作下程式看看效果,這裡的效果是用一個線程下載下傳圖檔的效果,可能有一些不完整,想看看效果自己動手試試,郁悶,家裡的網絡卡,gif的圖檔出不來效果,隻能明天上傳圖檔啦,公司也上傳不了動畫效果,我去,那我就貼一張普通圖檔,哈哈

Android 異步加載圖檔,使用LruCache和SD卡或手機緩存,效果非常的流暢

好了,今天的講解到此結束,有疑問的朋友請在下面留言,源碼裡面gridview的布局檔案 columnwedth設定了120dip,有點醜,大家可以改成90dip

繼續閱讀