从服务端加载图片(Volley框架+Gson框架+PullToRefresh框架)

来源:互联网 发布:pe砧板 知乎 编辑:程序博客网 时间:2024/06/06 07:18


先看服务端的代码(对象封装类和servlet类)

ShopInfo.java(get、set、构造器、toString方法省略)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private String name;  
  2. private String img;  
ShopListServlet.java

[java] view plaincop在CODE上查看代码片派生到我的代码片
  1. package com.atguigu.dianpin_server.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7.   
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.http.HttpServlet;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12.   
  13. import com.google.gson.Gson;  
  14.   
  15. /** 
  16.  * 获取分页ShopList的json字符串 
  17.  */  
  18. public class ShopListServlet extends HttpServlet {  
  19.     private List<ShopInfo> infos;  
  20.   
  21.     protected void doGet(HttpServletRequest request,  
  22.             HttpServletResponse response) throws ServletException, IOException {  
  23.   
  24.         init();  
  25.   
  26.         // 得到start和count的请求参数  
  27.         int start = Integer.parseInt(request.getParameter("start"));  
  28.         int count = Integer.parseInt(request.getParameter("count"));  
  29.         // 如果start太大, 就返回一个空串  
  30.         // 15 start=15  
  31.         if (start >= infos.size()) {  
  32.             response.getWriter().write("");  
  33.             return;  
  34.         }  
  35.         // 从集合中取当前请求页的数据集合  
  36.         List<ShopInfo> data = new ArrayList<ShopInfo>();  
  37.   
  38.         // 11 start=10&count=5  
  39.         if (start + count > infos.size()) {  
  40.             count = infos.size() - start;  
  41.         }  
  42.         for (int i = 0; i < count; i++) {  
  43.             data.add(infos.get(start + i));  
  44.         }  
  45.   
  46.         // 转换为json字符串  
  47.         String json = new Gson().toJson(data);  
  48.   
  49.         // 写到客户端  
  50.         response.setContentType("text/json;charset=utf-8");  
  51.         response.getWriter().write(json);  
  52.         // [{"name":"商铺名称1", "img":"f1.jpg"},{"name":"商铺名称2", "img":"f12.jpg"}]  
  53.     }  
  54.   
  55.     public void init() {  
  56.   
  57.         if (infos == null) {  
  58.             infos = new ArrayList<ShopInfo>();  
  59.             // 得到/image的真实路径  
  60.             String imagesPath = getServletContext().getRealPath("/image");  
  61.             // 得到路径对象  
  62.             File dirFile = new File(imagesPath);  
  63.             // 得到所有图片file对象  
  64.             File[] files = dirFile.listFiles();  
  65.             // 遍历  
  66.             for (int i = 0; i < files.length; i++) {  
  67.                 // 将图片信息封装为一个shopinfo对象, 并保存到集合中  
  68.                 String imageName = files[i].getName();  
  69.                 String name = "商铺名称 " + (i + 1);  
  70.                 infos.add(new ShopInfo(name, imageName));  
  71.             }  
  72.         }  
  73.     }  
  74. }  
--------------------------------------------分割线-------------------------------------------------------------------
看android代码

先贴出布局来

activity_main.xml

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="fill_parent"  
  3.     android:layout_height="fill_parent" >  
  4.       
  5.     <com.handmark.pulltorefresh.library.PullToRefreshListView  
  6.         android:id="@+id/lv_main"  
  7.         android:layout_width="match_parent"  
  8.         android:layout_height="match_parent" />  
  9.       
  10.     <ProgressBar  
  11.         android:id="@+id/pb_main"  
  12.         style="?android:attr/progressBarStyleLarge"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"   
  15.         android:layout_gravity="center"/>  
  16.   
  17. </FrameLayout>  
list_item.xml
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="100dp"  
  5.     android:orientation="horizontal"  
  6.     android:gravity="center_vertical">  
  7.   
  8.     <com.android.volley.toolbox.NetworkImageView  
  9.         android:id="@+id/iv_img"  
  10.         android:layout_width="90dp"  
  11.         android:layout_height="90dp"/>  
  12.   
  13.     <TextView  
  14.         android:id="@+id/tv_name"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:text="描述文本"   
  18.         android:layout_marginLeft="20dp"  
  19.         android:textSize="20sp"/>  
  20. </LinearLayout>  
listview_foot.xml
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="horizontal"   
  6.     android:gravity="center"  
  7.     android:clickable="false"  
  8.     android:focusable="false">  
  9.     <ProgressBar  
  10.         android:id="@+id/pb_foot"  
  11.         style="?android:attr/progressBarStyle"  
  12.         android:layout_width="wrap_content"  
  13.         android:layout_height="wrap_content"/>  
  14.     <TextView  
  15.         android:id="@+id/tv_foot"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:text="正在加载中..." />  
  19. </LinearLayout>  
  20. <!--   
  21.     1. 如果还有更多数据, 它就会显示  
  22.     2. 如果没有更多数据: 隐藏ProgressBar, 更新TextView的文本  
  23.  -->  

ShopInfo.java(get、set、构造器、toString方法省略)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private String name;  
  2. private String img;  

VolleyTool.java(框架的工具类)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.atguigu.day03_test;  
  2. import android.content.Context;  
  3. import android.graphics.Bitmap;  
  4. import android.support.v4.util.LruCache;  
  5. import com.android.volley.RequestQueue;  
  6. import com.android.volley.toolbox.ImageLoader;  
  7. import com.android.volley.toolbox.ImageLoader.ImageCache;  
  8. import com.android.volley.toolbox.Volley;  
  9.   
  10. public class VolleyTool {  
  11.     //初始化请求队列、图片加载器  
  12.     private RequestQueue queue;  
  13.     private ImageLoader imageLoader;  
  14.   
  15.     //私有静态实例  
  16.     private static VolleyTool instance;  
  17.     //私有构造方法  
  18.     private VolleyTool(Context context) {  
  19.         //创建请求队列  
  20.         queue = Volley.newRequestQueue(context);  
  21.         //创建图片加载器  
  22.         imageLoader = new ImageLoader(queue, new LruImageCache());  
  23.     }  
  24.     //公共、静态的方法  
  25.     public static VolleyTool getInstance(Context context) {  
  26.         if (instance == null) {  
  27.             instance = new VolleyTool(context);  
  28.         }  
  29.         return instance;  
  30.     }  
  31.   
  32.     //得到请求队列  
  33.     public RequestQueue getQueue() {  
  34.         return queue;  
  35.     }  
  36.     //得到图片加载器  
  37.     public ImageLoader getImageLoader() {  
  38.         return imageLoader;  
  39.     }  
  40.   
  41.     /** 
  42.      * 使用LRU回收算法的缓存类 
  43.      */  
  44.     class LruImageCache implements ImageCache {  
  45.   
  46.         // 缓存容器  
  47.         private LruCache<String, Bitmap> cache;  
  48.   
  49.         public LruImageCache() {  
  50.             // 计算缓存的最值  
  51.             int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);  
  52.             //创建缓存对象实例  
  53.             cache = new LruCache<String, Bitmap>(maxSize) {  
  54.                 @Override  
  55.                 protected int sizeOf(String key, Bitmap value) {  
  56.                     // 返回bitmap占用的内存大小  
  57.                     return value.getRowBytes() * value.getHeight();  
  58.                 }  
  59.             };  
  60.         }  
  61.   
  62.         // 从缓存中取图片对象  
  63.         @Override  
  64.         public Bitmap getBitmap(String url) {  
  65.             return cache.get(url);  
  66.         }  
  67.   
  68.         // 将图片对象保存到缓存容器中  
  69.         @Override  
  70.         public void putBitmap(String url, Bitmap bitmap) {  
  71.             cache.put(url, bitmap);  
  72.         }  
  73.   
  74.     }  
  75. }  
MainActivity.java

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.atguigu.day03_test;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. import android.widget.BaseAdapter;  
  11. import android.widget.ListView;  
  12. import android.widget.ProgressBar;  
  13. import android.widget.TextView;  
  14. import android.widget.Toast;  
  15.   
  16. import com.android.volley.Request;  
  17. import com.android.volley.RequestQueue;  
  18. import com.android.volley.Response;  
  19. import com.android.volley.Response.Listener;  
  20. import com.android.volley.VolleyError;  
  21. import com.android.volley.toolbox.NetworkImageView;  
  22. import com.android.volley.toolbox.StringRequest;  
  23. import com.google.gson.Gson;  
  24. import com.google.gson.reflect.TypeToken;  
  25. import com.handmark.pulltorefresh.library.PullToRefreshBase;  
  26. import com.handmark.pulltorefresh.library.PullToRefreshListView;  
  27.   
  28. public class MainActivity extends Activity {  
  29.     // 进度条  
  30.     private ProgressBar pb_main;  
  31.     // 请求队列  
  32.     RequestQueue requestQueue;  
  33.   
  34.     // 显示存放服务端数据的listView  
  35.     private PullToRefreshListView lv_main;  
  36.     // 数据对象集合  
  37.     private List<ShopInfo> data = new ArrayList<ShopInfo>();  
  38.     // 适配器  
  39.     private MainAdapter adapter;  
  40.   
  41.     @Override  
  42.     protected void onCreate(Bundle savedInstanceState) {  
  43.         super.onCreate(savedInstanceState);  
  44.         setContentView(R.layout.activity_main);  
  45.         // 定义的PullToRefreshListView需要转型  
  46.         lv_main = (PullToRefreshListView) findViewById(R.id.lv_main);  
  47.         // 下拉刷新的监听  
  48.         lv_main.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {  
  49.             @Override  
  50.             public void onRefresh(PullToRefreshBase<ListView> refreshView) {  
  51.                 //定义一个标示,如果为true,代表下拉  
  52.                 loadData(true);  
  53.             }  
  54.         });  
  55.         // 上拉加载的刷新  
  56.         lv_main.setOnLastItemVisibleListener(new PullToRefreshBase.OnLastItemVisibleListener() {  
  57.             @Override  
  58.             public void onLastItemVisible() {  
  59.                 // pb_foot.isShown()说明数据没有加载完毕  
  60.                 if (pb_foot.isShown()) {  
  61.                     //定义一个标示,如果为false,代表上拉  
  62.                     loadData(false);  
  63.                 }  
  64.             }  
  65.         });  
  66.         // 创建进度条对象  
  67.         pb_main = (ProgressBar) findViewById(R.id.pb_main);  
  68.         // 得到请求队列  
  69.         requestQueue = VolleyTool.getInstance(getApplicationContext())  
  70.                 .getQueue();  
  71.   
  72.         // 添加一个footView(上拉松开加载)  
  73.         addFootView();  
  74.   
  75.         // 初始化加载数据显示(false或者true均可)  
  76.         loadData(false);  
  77.     }  
  78.   
  79.     /** 
  80.      * 添加一个footView 1. 如果还有更多数据, 它就会显示 2. 如果没有更多数据: 隐藏ProgressBar, 更新TextView的文本 
  81.      */  
  82.     private ProgressBar pb_foot;  
  83.     private TextView tv_foot;  
  84.   
  85.     private void addFootView() {  
  86.         View footView = View.inflate(this, R.layout.listview_foot, null);  
  87.         pb_foot = (ProgressBar) footView.findViewById(R.id.pb_foot);  
  88.         tv_foot = (TextView) footView.findViewById(R.id.tv_foot);  
  89.         lv_main.getRefreshableView().addFooterView(footView);  
  90.     }  
  91.   
  92.     /* 
  93.      * 页面上下滑动,如果还没有加载完毕,就快速滑动过去 
  94.      * 这样消耗内存 定义一个标记,标记的意思是--某次请求是否正在加载图片(默认没有加载,表明已经加载过) 
  95.      */  
  96.     private boolean loading = false;  
  97.   
  98.     private void loadData(final boolean reset) {  
  99.   
  100.         /* 
  101.          * 如果正在加载,直接结束,从新滑到的图片无需继续加载了 
  102.          */  
  103.         if (loading)  
  104.             return;  
  105.         // 一旦方法执行,就将标记改成true,说明正在加载  
  106.         loading = true;  
  107.   
  108.         // 计算start-如果加载第一页就是0,如果不是第一页就是data.size  
  109.         int start = reset ? 0 : data.size();  
  110.         // data.size()==10 -->start=10  
  111.         String url = "http://192.168.30.41:8090/dianpin_03/ShopListServlet?start="  
  112.                 + start + "&count=5";  
  113.   
  114.         // 创建一个请求  
  115.         Request request = new StringRequest(url, new Listener<String>() {  
  116.   
  117.             @Override  
  118.             public void onResponse(String response) {  
  119.                 /* 
  120.                  * 从服务器得到数据,一旦该方法触发,说明某次请求已经加载完毕图片了 要将标记改为false,说明已经加载完毕,无需加载了 
  121.                  */  
  122.                 loading = false;  
  123.   
  124.                 /* 
  125.                  * 即使加载完毕,如果继续往下拉的话,还会发送请求 这里需要判断服务器端返回null值的情况(查看服务端代码) 
  126.                  */  
  127.                 if ("".equals(response)) {  
  128.                     // 隐藏ProgressBar, 更新TextView的文本  
  129.                     pb_foot.setVisibility(View.GONE);  
  130.                     tv_foot.setText("已加载完部数据");  
  131.                     // 将该方法直接返回,无需继续往下执行了  
  132.                     return;  
  133.                 }  
  134.   
  135.                 // 将服务器端的json数组解析为ShopInfo对象集合  
  136.                 List<ShopInfo> newData = new Gson().fromJson(response,  
  137.                         new TypeToken<List<ShopInfo>>() {  
  138.                         }.getType());  
  139.   
  140.                 // 因为每次请求5个json对象,如果返回小于5说明已经加载完所有的数据了  
  141.                 if (newData.size() < 5) {  
  142.                     // 隐藏ProgressBar, 更新TextView的文本  
  143.                     pb_foot.setVisibility(View.GONE);  
  144.                     tv_foot.setText("已加载完部数据");  
  145.                 }  
  146.   
  147.                 /* 
  148.                  * 第一次加载 lv_main.setAdapter(adapter); 
  149.                  * 说明只显示第一页的数据 
  150.                  */  
  151.                   
  152.                 if (adapter == null) {  
  153.                     data = newData;  
  154.                     adapter = new MainAdapter();  
  155.                     lv_main.setAdapter(adapter);  
  156.                     pb_main.setVisibility(View.GONE);  
  157.                 } else {  
  158.                     if (reset) {  
  159.                         // 如果适配器不为null,并且下拉刷新,需要清空数据,只加载第一页  
  160.                         data.clear();  
  161.                         // 显示加载更多  
  162.                         pb_foot.setVisibility(View.VISIBLE);  
  163.                         tv_foot.setText("下拉加载更多");  
  164.                         lv_main.onRefreshComplete();  
  165.                     }  
  166.                     // 不是第一次加载,就需要将每次获取的数据放到data集合中  
  167.                     data.addAll(newData);  
  168.                     adapter.notifyDataSetChanged();  
  169.                 }  
  170.             }  
  171.         }, new Response.ErrorListener() {  
  172.             @Override  
  173.             public void onErrorResponse(VolleyError error) {  
  174.                 Toast.makeText(getApplicationContext(), "请求服务器异常"0).show();  
  175.             }  
  176.         });  
  177.         // 将请求添加到队列中, 自动处理  
  178.         requestQueue.add(request);  
  179.   
  180.     }  
  181.   
  182.     /** 
  183.      * 适配器代码 
  184.      */  
  185.     class MainAdapter extends BaseAdapter {  
  186.   
  187.         @Override  
  188.         public int getCount() {  
  189.             return data.size();  
  190.         }  
  191.   
  192.         @Override  
  193.         public Object getItem(int position) {  
  194.             return data.get(position);  
  195.         }  
  196.   
  197.         @Override  
  198.         public long getItemId(int position) {  
  199.             return 0;  
  200.         }  
  201.   
  202.         @Override  
  203.         public View getView(int position, View convertView, ViewGroup parent) {  
  204.             ViewHolder holder = null;  
  205.             if (convertView == null) {  
  206.                 holder = new ViewHolder();  
  207.                 convertView = View.inflate(getApplicationContext(),  
  208.                         R.layout.list_item, null);  
  209.                 holder.imageView = (NetworkImageView) convertView  
  210.                         .findViewById(R.id.iv_img);  
  211.                 holder.textView = (TextView) convertView  
  212.                         .findViewById(R.id.tv_name);  
  213.                 convertView.setTag(holder);  
  214.             } else {  
  215.                 holder = (ViewHolder) convertView.getTag();  
  216.             }  
  217.   
  218.             ShopInfo shopInfo = data.get(position);  
  219.             holder.textView.setText(shopInfo.getName());  
  220.   
  221.             // 设置未加载默认图片  
  222.             holder.imageView.setDefaultImageResId(R.drawable.default_icon);  
  223.             // 设置加载异常的图片  
  224.             holder.imageView.setErrorImageResId(R.drawable.error);  
  225.             // 动态加载图片  
  226.             String url = "http://192.168.30.41:8090/dianpin_03/image/"  
  227.                     + shopInfo.getImg();  
  228.             holder.imageView.setImageUrl(url,  
  229.                     VolleyTool.getInstance(getApplicationContext())  
  230.                             .getImageLoader());  
  231.   
  232.             return convertView;  
  233.         }  
  234.   
  235.         class ViewHolder {  
  236.             NetworkImageView imageView;  
  237.             TextView textView;  
  238.         }  
  239.     }  
  240. }  



0 0
原创粉丝点击