Android批量图片加载经典系列——Volley框架实现多布局的新闻列表

一、问题描述

  Volley是Google 2013年发布的实现Android平台上的网络通信库,主要提供网络通信和图片下载的解决方案,比如以前从网上下载图片的步骤可能是这样的流程:

在ListAdapter的getView()里开始图像的读取。

  通过AsyncTask等机制使用HttpURLConnection从服务器去的图片资源,在AsyncTask的onPostExecute()里设置相应ImageView的属性.而在Volley下,只需要ImageLoader即可实现。

  案例介绍——现图片新闻浏览:

二、案例主要组件

1、  RequestQueue 请求队列将StringRequest请求放入队列,并进行异步处理,主要代码:

//创建RequestQueue,可发送异步请求
RequestQueue  mRequestQueue=Volley.newRequestQueue(this);
//StringRequest request=new StringRequest(…);//创建一个客户端请求
mRequestQueue.add(request);//将请求加到队列,将异步执行请求

2、ImageLoader 实现缓存并异步加载网络图片

//创建ImageLoader,用于将图片存入缓存和从缓存中取出图片
//第一个参数为之前创建的RequestQueue对象
//第二参数为图片缓存设置,详解见BitmapCache代码
ImageLoader mImageLoader=new
ImageLoader(mRequestQueue,new BitmapCache());
//加载图片,先从内存中加载,内存没有再从网络加载
//url:图片网络路径
//view 显示图片的ImageView控件,R.drawable.default未加载完成显示的缺省图片 ,R.drawable.error加载失败显示的图片
        mImageLoader.get(url,ImageLoader.getImageListener(view,
                R.drawable.default, R.drawable.error));    
三、案例完整代码

注:服务端环境需要自行搭建

1、  BitmapCache和SunNewsApplication组件:

  (1)BitmapCache:

public class BitmapCache implements ImageCache{
    private LruCache<String, Bitmap> mCache;
    public BitmapCache(){
    // 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常
    // 使用最大可用内存值的1/8作为缓存的大小。
    int maxsize=(int)(Runtime.getRuntime().maxMemory()/1024)/8;
    mCache=new LruCache<String, Bitmap>(maxsize){
    // 重写此方法来衡量每张图片的大小,默认返回图片数量
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return super.sizeOf(key, value);
            }
        };
    }
    /**
     * 获取缓存中图片
     */
    @Override
    public Bitmap getBitmap(String key) {
        return mCache.get(key);
    }
    /**
     * 存入缓存
     */
    @Override
    public void putBitmap(String key, Bitmap bitmap) {
        if(bitmap!=null)mCache.put(key, bitmap);
    }

}

(2)SunNewsApplication:

public class SunNewsApplication extends Application {
private ImageLoader mImageLoader;
       private RequestQueue mRequestQueue;

public void onCreate(){
//创建RequestQueue,可发送异步请求
mRequestQueue=Volley.newRequestQueue(this);
//创建ImageLoader,用于将图片存入缓存和从缓存中取出图片
mImageLoader=new ImageLoader(mRequestQueue,new BitmapCache());
        }
    public ImageLoader getmImageLoader() {
        return mImageLoader;
    }
    public RequestQueue getmRequestQueue() {
        return mRequestQueue;
    }
}

2、MoreStyleNewsListViewAdapter代码:

public class MoreStyleNewsListViewAdapter extends BaseAdapter {
    private Activity mActivity;
    private List<NewsItem> newsList;
    private ImageLoader imageLoader;

    public MoreStyleNewsListViewAdapter(Activity mActivity,List<NewsItem> newsList){
        this.mActivity=mActivity;
        this.newsList=newsList;
        imageLoader=((SunNewsApplication)mActivity.getApplication()).getmImageLoader();
    }
    private final int TYPE_COUNT=2;
    /**
     * 返回数据项的显示类型数据
     */
    @Override
    public int getItemViewType(int position) {
        return newsList!=null?newsList.get(position).getStyle():-1;
    }
    /**
     * 返回类型个数
     */
    @Override
    public int getViewTypeCount() {
        return TYPE_COUNT;
    }

    @Override
    public int getCount() {
        return newsList.size();
    }
    @Override
    public Object getItem(int position) {
        return newsList.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder=null;
        NewsItem item=newsList.get(position);
        if(convertView==null){
        holder=new ViewHolder();
        //将layout.xml转换为View
        switch(item.getStyle()){
            case 0:
            convertView=LayoutInflater.from(mActivity).inflate(R.layout.news_item1, null);
                holder.ivImg1=(ImageView)convertView.findViewById(R.id.ivNewsImg);
                break;
            case 1:
            convertView=LayoutInflater.from(mActivity).inflate(R.layout.news_item2, null);
                holder.ivImg1=(ImageView)convertView.findViewById(R.id.ivImg1);
                holder.ivImg2=(ImageView)convertView.findViewById(R.id.ivImg2);
                holder.ivImg3=(ImageView)convertView.findViewById(R.id.ivImg3);
                break;
            }
        holder.tvTilte=(TextView)convertView.findViewById(R.id.tvTitle);
        convertView.setTag(holder);//记录个标识
        }else{
            holder=(ViewHolder)convertView.getTag();
        }
        //向ui元素绑定数据
        holder.tvTilte.setText(item.getTitle());
//加载图片,先从内存中加载,内存没有再从网络加载
        imageLoader.get(item.getImgUrl()[0], ImageLoader.getImageListener(holder.ivImg1,
                R.drawable.default_big, R.drawable.default_big));
        switch(item.getStyle()){
        case 1:
imageLoader.get(item.getImgUrl()[1], ImageLoader.getImageListener(holder.ivImg2,
                        R.drawable.default_big, R.drawable.default_big));                    imageLoader.get(item.getImgUrl()[2], ImageLoader.getImageListener(holder.ivImg3,
                        R.drawable.default_big, R.drawable.default_big));                    break;
        }
        Log.d("jereh","getView()");
        return convertView;
    }
    private class ViewHolder{
        private TextView tvTilte;
        private ImageView ivImg1;
        private ImageView ivImg2;
        private ImageView ivImg3;
    }
}

3、MainActivity代码

public class MainActivity extends Activity {
    private RadioGroup rgChannel;
    private List<NewsItem> newsList=new ArrayList<NewsItem>();
    private MoreStyleNewsListViewAdapter adapter;
    private ListView newsListView;
    private RequestQueue queue;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        queue=((SunNewsApplication)super.getApplication()).getmRequestQueue();
        initView();
        requestData();

    }
    private void initView(){
        rgChannel=(RadioGroup)super.findViewById(R.id.rgChannel);
        rgChannel.check(R.id.rbToday);
        newsListView=(ListView)super.findViewById(R.id.lvNews);
        adapter=new MoreStyleNewsListViewAdapter(this,newsList);
        newsListView.setAdapter(adapter);
    }

    /**
     * 异步请求获得网络数据
     */
    private void requestData(){
        String url="http://192.168.0.107:8080/21-sun/NewsListServlet";
        StringRequest request=new StringRequest(Method.GET,url,
         new Response.Listener<String>() {
            @Override
            public void onResponse(String ret) {//请求成功调用并返回结果
                Gson gson=new Gson();
                List list=gson.fromJson(ret,
new TypeToken<ArrayList<NewsItem>>(){}.getType());
                newsList.addAll(list);
                adapter.notifyDataSetChanged();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {//请求失败调用
                Log.d("jereh", "网络加载失败!");
            }
        });
        queue.add(request);//将请求加到队列,将异步执行请求
    }
}

4、NewsItem实体类

public class NewsItem {
private String title;//新闻标题
    private int style; //0:普通 1:多图 2:
        private String[] imgUrl;//新闻图片
        …//省略setter/getter
}

5、服务端NewsListServlet代码

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/json;charset=utf-8");
    List<NewsItem> newsList=new ArrayList<NewsItem>();
    NewsItem item1=new NewsItem();
    item1.setTitle("英达成唯一获新疆最高信用等级的养护施工企业");
    item1.setStyle(0);
    item1.setImgUrl( new
String[]{"http://news.21-sun.com/UserFiles/x_Image/x_20150624164627_0.jpg"});
    newsList.add(item1);
…
    NewsItem item4=new NewsItem();
    item4.setTitle("德工2015路面机械质量万里行活动走进河南");
    item4.setStyle(1);
item4.setImgUrl(new
String[]{"http://news.21-sun.com/UserFiles/x_Image/x_20150624101251_0.jpg",
        "http://news.21-sun.com/UserFiles/x_Image/x_20150624080852_0.jpg",
        "http://news.21-sun.com/UserFiles/x_Image/x_20150623141354_0.jpg"});
    newsList.add(item4);
    NewsItem item5=new NewsItem();
    item5.setTitle("德州宝鼎总经理王桂清:实在女人爱学习");
    item5.setStyle(0);
    item5.setImgUrl(new String[]{"http://news.21-sun.com/UserFiles/x_Image/x_20150624123300_0.jpg"});
    newsList.add(item5);
    JSONArray jsonArr=JSONArray.fromObject(newsList);
    System.out.println(jsonArr);
response.getWriter().print(jsonArr.toString());
    }

  想要了解更多内容的小伙伴,可以点击查看源码,亲自运行测试。

  疑问咨询或技术交流,请加入官方QQ群: (452379712)

作者:杰瑞教育

出处:http://blog.csdn.net/jerehedu

本文版权归烟台杰瑞教育科技有限公司和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

时间: 2024-08-28 10:13:07

Android批量图片加载经典系列——Volley框架实现多布局的新闻列表的相关文章

Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载

一.问题描述 在之前的系列文章中,我们使用了Volley和Xutil框架实现图片的缓存加载(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html#pltpjz),接下来我们再介绍一下afinal 框架的使用. Afinal 是一个android的http框架.sqlite orm 和 ioc 框架.使其更加简单易用,Afinal的宗旨是简洁,快速.约定配置的方式之后,尽量一行代码完成所有事情,代码入侵性小,在三者中比较推荐.在这里我们主要使用

Android批量图片加载经典系列——采用二级缓存、异步加载网络图片

一.问题描述 Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络.内存缓存(一级)本质上是Map集合以key-value对的方式存储图片的url和Bitmap信息,由于内存缓存会造成堆内存泄露, 管理相对复杂一些,可采用第三方组件,对于有经验的可自己编写组件,而文件缓存比较简单通常自己封装一下即可.下面就通过案例看如何实现网络图片加载的优化. 二.案例介绍 案例新

Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片

一.问题描述 为提高图片加载的效率,需要对图片的采用缓存和异步加载策略,编码相对比较复杂,实际上有一些优秀的框架提供了解决方案,比如近期在git上比较活跃的xutil框架 Xutil框架提供了四大模块: 1.  DbUtil模块:采用ORM机制简化Sqlite操作,一行代码就可执行增删改查.支持事务.支持延迟策略 2.  ViewUtils模块:可以说是Android的IOC框架,可以注解方式对ui.资源.事件进行绑定 3.  HttpUtils模块:支持同步.异步请求.支持大文件上传 4. 

Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片

一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除无效的异步线程;保证异步加载图片时不会乱序 3.只对当前屏幕可见部分进行缓存.异步加载图片 4.优化性能杜绝OOM 二.案例介绍 案例实现照片墙效果 三.主要技术 LruCache 内存缓存技术,在Android中 专门用来做图片缓存处理的组件,主要使用步骤 (1) 设置缓存图片的内存大小,如设置为

Android批量图片加载经典系列——使用二级缓存、异步网络负载形象

一.问题描写叙述 Android应用中常常涉及从网络中载入大量图片,为提升载入速度和效率,降低网络流量都会採用二级缓存和异步载入机制.所谓二级缓存就是通过先从内存中获取.再从文件里获取,最后才会訪问网络.内存缓存(一级)本质上是Map集合以key-value对的方式存储图片的url和Bitmap信息.因为内存缓存会造成堆内存泄露, 管理相对复杂一些.可採用第三方组件,对于有经验的可自己编写组件,而文件缓存比較简单通常自己封装一下就可以. 以下就通过案例看怎样实现网络图片载入的优化. 二.案例介绍

android webView 图片加载不出来 后台报错Uncaught TypeError: Cannot call method &#39;getElementsByTagName&#39; of null

在之前,webView加载图片完全没有问题.直到前端H5开发换新的加载图片的方式,导致图片忽然加载不出来了. 从后台日志看到了webview 打印了报错信息 Cannot call method 'getElementsByTagName' of null 我怀疑是不是由于此处报错终止了图片加载的进程. 分析此处错误出现的原因: 由于调用的H5界面的js其中的写法不规范,webView在加载的时候,调用的doom模型为空,导致了其图片没有加载出来 解决办法: 在客户端webView.getSet

Android图片加载与缓存开源框架:Android Glide

<Android图片加载与缓存开源框架:Android Glide> Android Glide是一个开源的图片加载和缓存处理的第三方框架.和Android的Picasso库类似,个人感觉比Android Picasso好用.Android Glide使自身内部已经实现了缓存策略,使得开发者摆脱Android图片加载的琐碎事务,专注逻辑业务的代码.Android Glide使用便利,短短几行简单明晰的代码,即可完成大多数图片从网络(或者本地)加载.显示的功能需求. 使用Android Gl

Android开发之搜芽项目的图片加载问题(使用Volley进行网络图片加载)

搜芽的移动开发这几天进度相对来说非常的快.但是美中不足的就是网络图片的加载问题.我有两套方案: 1)沿用迅雷动漫的图片加载.迅雷动漫也是用的一个开源的库.但是不知道是我使用出了问题还是真的是它的问题.在我迅速的下拉和回倒的时候, 不确定的会出现崩溃.logcat显示loadImage里面出现了内存溢出.out of memory..这个我想应该不是我的问题. 2)采用外包的AsyncImageLoader.这个文件我没有仔细看.然后实验结果是,加载图片巨慢.而且容易导致卡顿. 所以,我将希望转向

Android中图片加载框架Glide解析2----从源码的角度理解Glide的执行流程

转载地址:http://blog.csdn.net/guolin_blog/article/details/53939176 在本系列的上一篇文章中,我们学习了Glide的基本用法,体验了这个图片加载框架的强大功能,以及它非常简便的API.还没有看过上一篇文章的朋友,建议先去阅读 Android图片加载框架最全解析(一),Glide的基本用法 . 在多数情况下,我们想要在界面上加载并展示一张图片只需要一行代码就能实现,如下所示: Glide.with(this).load(url).into(i