listview,gridview 动态加载网络图片
来源:互联网 发布:开展数据库系统培训 编辑:程序博客网 时间:2024/05/21 14:50
最近在做一个android播放器客户端。需要把服务器上的资源信息拉到手机上显示。这就离不开listview。一开始我举得很容易的,但真正做起来就会出现很多意想不到的问题。比如说listview滑动不流畅,图片加载混乱,甚至会有OOM。等等这些问题我都碰到过,可能我是菜鸟,这些低级的问题都被我碰到了,但我很肯定的说,以后再做类似的事情,问题就迎刃而解了。
说一下listview 和gridview的区别。其实没有什么区别,我们能理解生活中用到的桶和盆有什么区别,就能理解这两个的区别,同样的容器,只是外表不一样而已。实现方式都会是new 一个adapter出来,然后用listview(gridview).setAdapter(adapter)。再加一些监听之类的就差不多了。
说了半天,还没进入主题。listview加载网络图片的实现,我有找过很多资料,但用的都不是很符合自己的要求。最后找到了一个高手的code,得以解决之。添加url在此:http://www.cnblogs.com/liongname/articles/2345087.html
文章中只有用到临时缓存,我这里再添加一个存储,保存到sdcard。
首先我们要实现一个异步加载图片的类,用来对listview的每一个item加载图片:
public enum BitmapManager { INSTANCE; public static final String TAG = "BitmapManager"; private final Map<String, SoftReference<Bitmap>> cache; //对图片做缓存 private final ExecutorService pool; private Map<ImageView, String> imageViews = Collections .synchronizedMap(new WeakHashMap<ImageView, String>()); private Bitmap placeholder; BitmapManager() { cache = new HashMap<String, SoftReference<Bitmap>>(); pool = Executors.newFixedThreadPool(5); //线程池 } public void setPlaceholder(Bitmap bmp) { //设置占位图,如果加载未完成前应该显示的图片 placeholder = bmp; } public Bitmap getBitmapFromCache(String url) { if (cache.containsKey(url)) { return cache.get(url).get(); } return null; } public void queueJob(final String url, final ImageView imageView, final int width, final int height) { /* Create handler in UI thread. */ final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String tag = imageViews.get(imageView); if (tag != null && tag.equals(url)) { //根据url对应的ImageView 设置图片显示 if (msg.obj != null) { imageView.setImageBitmap((Bitmap) msg.obj); } else { imageView.setImageBitmap(placeholder); Log.d(null, "fail " + url); } } } }; pool.submit(new Runnable() { //线程异步load图片 @Override public void run() { final Bitmap bmp = downloadBitmap(url, width, height); Message message = Message.obtain(); message.obj = bmp; Log.d(null, "Item downloaded: " + url); handler.sendMessage(message); } }); } public void loadBitmap(final String url, final ImageView imageView, final int width, final int height) { imageViews.put(imageView, url); //对传进来的imageView 和url做关联,防止图片混乱 Bitmap bitmap = getBitmapFromCache(url); // check in UI thread, so no concurrency issues if (bitmap != null) { Log.d(null, "Item loaded from cache: " + url); imageView.setImageBitmap(bitmap); } else { imageView.setImageBitmap(placeholder); queueJob(url, imageView, width, height); } } private Bitmap downloadBitmap(String url, int width, int height) { Bitmap sdcardFile = getSDCardBitmap(url); //优先从sdcard中取图片 if(sdcardFile != null){ sdcardFile = Bitmap.createScaledBitmap(sdcardFile, width, height, true); cache.put(url, new SoftReference<Bitmap>(sdcardFile)); return sdcardFile; } try { Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL( url).getContent()); bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true); saveSDCardBitmap(url,bitmap); //存入sdcard; cache.put(url, new SoftReference<Bitmap>(bitmap)); return bitmap; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private void saveSDCardBitmap(String url,Bitmap bm){ String filePath = Environment.getExternalStorageDirectory()+"/imagecache/"+url.substring(url.lastIndexOf("/")+1); //从url中取文件名以保存到sdcard,方便取。 final File f = new File(filePath); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ File path = new File(Environment.getExternalStorageDirectory()+"/imagecache");if(!path.exists()){path.mkdirs();}try {FileOutputStream out = new FileOutputStream(f);bm.compress(Bitmap.CompressFormat.PNG, 100, out);out.flush();out.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch(IOException e){e.printStackTrace(); } } } private Bitmap getSDCardBitmap(String url){ String filePath = Environment.getExternalStorageDirectory()+"/imagecache/"+url.substring(url.lastIndexOf("/")+1); final File f = new File(filePath); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //sdcard 是否存在 File path = new File(Environment.getExternalStorageDirectory()+"/imagecache");if(!path.exists()){path.mkdirs();}if(f.exists()){Bitmap tmp = BitmapFactory.decodeFile(filePath);return tmp;} } return null; }}
这个类写好后,我们就只需要在Adapter中的getView()方法中调用这个类就行了。
下面我们来看getView()方法:
public View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if(convertView == null){holder = new ViewHolder();convertView = mInflater.inflate(R.layout.list_unit,null); /获取list单元布局holder.Image = (ImageView)findViewById(R.id.mImage);holder.Title = (TextView)findViewbyId(R.id.mTitle);convertView.setTag(hodler);//添加标签}else{holder = convertView.getTag();}if(!mBusy){BitmapManager.INSTANCE.setPlaceholder(bm); //设置默认图片 BitmapManager.INSTANCE.loadBitmap(url, holder.Image, imageWidth,imageHeight);}else{holder.Image.setImageBitmap(bm);}return convertView;}public static class ViewHolder{ ImageViwe Image;TextView Title;}OnScrollListener mScrollListener = new OnScrollListener() { //对listview的滚动监听@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {case OnScrollListener.SCROLL_STATE_FLING:ListViewAdapter.this.setFlagBusy(true);break;case OnScrollListener.SCROLL_STATE_IDLE:ListViewAdapter.this.setFlagBusy(false);break;case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:ListViewAdapter.this.setFlagBusy(false);break;default:break;}ListViewAdapter.this.notifyDataSetChanged();}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {}};protected void setFlagBusy(boolean b) {// TODO Auto-generated method stubmBusy = b; //全局变量 mBusy,表示listview是否滚动}
到这里,我们的ListView异步加载图片的主要工作基本完成。剩下的就是在activity中实例化以及set的工作。这个方法对ListView 和GridView都是通用的。目前我还没有发现有图片混乱,内存溢出,滑动不流畅等问题。当然,再次申明,这里的大部分代码不是我的,我只是拿来优化成了一个适合我自己的东西了。平时都忙着coding,对于很多临时找到的好东西,自己感悟出来的东西(当然很少了),都没有及时记下来,等到需要时又找不到了,不得不说这是一大损失。
- listview,gridview 动态加载网络图片
- Android Listview异步动态加载网络图片
- Android ListView,Gridview动态加载释放图片资源
- ListView GridView ViewPager 异步 加载网络图片 缓存到本地
- GridView加载网络图片
- ListView与GridView异步加载图片
- ListView,GridView高效异步加载图片
- Android ListView和GridView异步加载图片
- ListView、GridView滑动时禁止加载图片
- ListView与GridView异步加载图片
- 使用ListView加载网络图片
- listview 异步加载 网络图片
- 安卓GridView异步加载网络图片
- 用GridView加载网络图片(上)
- cocos2dx 动态加载网络图片
- ViewPager+动态加载网络图片
- ViewPager+动态加载网络图片
- ListView 列添加动态加载图片
- 帝国cms7 列表模板直接加下载地址
- python编码规范(转自:http://blog.csdn.net/yefengnidie/article/details/6721781)
- 字符串转换成json对象的方法
- 【流媒體】live555—VS2010 下live555编译、使用及测试
- 在程序中使用libcurl的的静态链接库产生的未导出符号的错误
- listview,gridview 动态加载网络图片
- mysql笔记
- ubuntu下apt-get 命令参数大全
- mysql主从库
- Spinner
- Cocos2d-x 的CCObject与autorelease 之深入分析
- 本周推荐10款免费的网站模板设计
- iOS学习笔记20—获取当前APP版本
- C# Dictionary序列化/反序列化