android之圖片非同步載入並緩衝到本地

來源:互聯網
上載者:User

           在android項目中訪問網狀圖片是非常普遍性的事情,如果我們每次請求都要訪問網路來擷取圖片,會非常耗費流量,而且圖片佔用記憶體空間也比較大,圖片過多且不釋放的話很容易造成記憶體溢出。針對上面遇到的兩個問題,首先耗費流量我們可以將圖片第一次載入上面緩衝到本地,以後如果本地有就直接從本地載入。圖片過多造成記憶體溢出,這個是最不容易解決的,要想一些好的緩衝策略,比如大圖片使用LRU緩衝策略或懶載入緩衝策略。今天首先介紹一下本機快取圖片。

           首先看一下非同步載入緩衝本地代碼:

 

public class AsyncBitmapLoader  {      /**      * 記憶體配置圖片軟引用緩衝      */      private HashMap<String, SoftReference<Bitmap>> imageCache = null;            public AsyncBitmapLoader()      {          imageCache = new HashMap<String, SoftReference<Bitmap>>();      }            public Bitmap loadBitmap(final ImageView imageView, final String imageURL, final ImageCallBack imageCallBack)      {          //在記憶體緩衝中,則返回Bitmap對象          if(imageCache.containsKey(imageURL))          {              SoftReference<Bitmap> reference = imageCache.get(imageURL);              Bitmap bitmap = reference.get();              if(bitmap != null)              {                  return bitmap;              }          }          else          {              /**              * 加上一個對本機快取的尋找              */              String bitmapName = imageURL.substring(imageURL.lastIndexOf("/") + 1);              File cacheDir = new File("/mnt/sdcard/test/");              File[] cacheFiles = cacheDir.listFiles();              int i = 0;              if(null!=cacheFiles){            for(; i<cacheFiles.length; i++)              {                  if(bitmapName.equals(cacheFiles[i].getName()))                  {                      break;                  }              }                            if(i < cacheFiles.length)              {                  return BitmapFactory.decodeFile("/mnt/sdcard/test/" + bitmapName);              }            }        }                    final Handler handler = new Handler()          {              /* (non-Javadoc)              * @see android.os.Handler#handleMessage(android.os.Message)              */              @Override              public void handleMessage(Message msg)              {                  // TODO Auto-generated method stub                  imageCallBack.imageLoad(imageView, (Bitmap)msg.obj);              }          };                    //如果不在記憶體緩衝中,也不在本地(被jvm回收掉),則開啟線程下載圖片          new Thread()          {              /* (non-Javadoc)              * @see java.lang.Thread#run()              */              @Override              public void run()              {                  // TODO Auto-generated method stub                  InputStream bitmapIs = HttpUtils.getStreamFromURL(imageURL);                                    Bitmap bitmap = BitmapFactory.decodeStream(bitmapIs);                  imageCache.put(imageURL, new SoftReference<Bitmap>(bitmap));                  Message msg = handler.obtainMessage(0, bitmap);                  handler.sendMessage(msg);                                    File dir = new File("/mnt/sdcard/test/");                  if(!dir.exists())                  {                      dir.mkdirs();                  }                                    File bitmapFile = new File("/mnt/sdcard/test/" +                           imageURL.substring(imageURL.lastIndexOf("/") + 1));                  if(!bitmapFile.exists())                  {                      try                      {                          bitmapFile.createNewFile();                      }                      catch (IOException e)                      {                          // TODO Auto-generated catch block                          e.printStackTrace();                      }                  }                  FileOutputStream fos;                  try                  {                      fos = new FileOutputStream(bitmapFile);                      bitmap.compress(Bitmap.CompressFormat.PNG,                               100, fos);                      fos.close();                  }                  catch (FileNotFoundException e)                  {                      // TODO Auto-generated catch block                      e.printStackTrace();                  }                  catch (IOException e)                  {                      // TODO Auto-generated catch block                      e.printStackTrace();                  }              }          }.start();                    return null;      }      public interface ImageCallBack      {          public void imageLoad(ImageView imageView, Bitmap bitmap);      }  }

     這是一個封裝好的非同步載入圖片類,緩衝了兩份,一份是使用軟引用緩衝到記憶體中,一份是緩衝到本地sd卡,如果記憶體中沒有,則從本地尋找,如果本地沒有則從網路擷取圖片。

public class HttpUtils {public static InputStream getStreamFromURL(String imageURL) {InputStream in=null;try {URL url=new URL(imageURL);HttpURLConnection connection=(HttpURLConnection) url.openConnection();in=connection.getInputStream();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return in;}}

    這是一個訪問網路擷取類。不細說了。

   下面看一下如何使用封裝好的非同步載入圖片的類:

public class ImageCacheActivity extends Activity {    /** Called when the activity is first created. */private ListView listview;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                listview=(ListView) findViewById(R.id.listView_list);        MyAdapter adapter=new MyAdapter();        listview.setAdapter(adapter);    }        private class MyAdapter extends BaseAdapter{    private AsyncBitmapLoader asyncBitmapLoader;    public MyAdapter(){    asyncBitmapLoader=new AsyncBitmapLoader();    }@Overridepublic int getCount() {// TODO Auto-generated method stubreturn 10;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubif(convertView==null){convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, null);}ImageView image=(ImageView) convertView.findViewById(R.id.addexam_list_icon);String imageURL="http://s.ata.net.cn/4f98db46908987a21a000003/logo/2012/04/114_80aaf295c083d07a496743699aac3193.png";Bitmap bitmap=asyncBitmapLoader.loadBitmap(image, imageURL, new ImageCallBack() {@Overridepublic void imageLoad(ImageView imageView, Bitmap bitmap) {// TODO Auto-generated method stubimageView.setImageBitmap(bitmap);}}); if(bitmap == null)          {     image.setImageResource(R.drawable.ic_launcher);          }          else          {          image.setImageBitmap(bitmap);          }            return convertView;}        }}

這樣就完成了,網路擷取不到bitmap則顯示預設圖片。

這是一種很實用的方法,大家自己試試吧!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.