标签:
依赖库:
先看服务端的代码(对象封装类和servlet类)
ShopInfo.java(get、set、构造器、toString方法省略)
private String name; private String img;ShopListServlet.java
package com.atguigu.dianpin_server.servlet;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
/**
* 获取分页ShopList的json字符串
*/
public class ShopListServlet extends HttpServlet {
private List<ShopInfo> infos;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
init();
// 得到start和count的请求参数
int start = Integer.parseInt(request.getParameter("start"));
int count = Integer.parseInt(request.getParameter("count"));
// 如果start太大, 就返回一个空串
// 15 start=15
if (start >= infos.size()) {
response.getWriter().write("");
return;
}
// 从集合中取当前请求页的数据集合
List<ShopInfo> data = new ArrayList<ShopInfo>();
// 11 start=10&count=5
if (start + count > infos.size()) {
count = infos.size() - start;
}
for (int i = 0; i < count; i++) {
data.add(infos.get(start + i));
}
// 转换为json字符串
String json = new Gson().toJson(data);
// 写到客户端
response.setContentType("text/json;charset=utf-8");
response.getWriter().write(json);
// [{"name":"商铺名称1", "img":"f1.jpg"},{"name":"商铺名称2", "img":"f12.jpg"}]
}
public void init() {
if (infos == null) {
infos = new ArrayList<ShopInfo>();
// 得到/image的真实路径
String imagesPath = getServletContext().getRealPath("/image");
// 得到路径对象
File dirFile = new File(imagesPath);
// 得到所有图片file对象
File[] files = dirFile.listFiles();
// 遍历
for (int i = 0; i < files.length; i++) {
// 将图片信息封装为一个shopinfo对象, 并保存到集合中
String imageName = files[i].getName();
String name = "商铺名称 " + (i + 1);
infos.add(new ShopInfo(name, imageName));
}
}
}
}
--------------------------------------------分割线-------------------------------------------------------------------先贴出布局来
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.handmark.pulltorefresh.library.PullToRefreshListView
android:id="@+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/pb_main"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>list_item.xml<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/iv_img"
android:layout_width="90dp"
android:layout_height="90dp"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="描述文本"
android:layout_marginLeft="20dp"
android:textSize="20sp"/>
</LinearLayout>
listview_foot.xml<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:clickable="false"
android:focusable="false">
<ProgressBar
android:id="@+id/pb_foot"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tv_foot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载中..." />
</LinearLayout>
<!--
1. 如果还有更多数据, 它就会显示
2. 如果没有更多数据: 隐藏ProgressBar, 更新TextView的文本
-->
ShopInfo.java(get、set、构造器、toString方法省略)
private String name; private String img;
VolleyTool.java(框架的工具类)
package com.atguigu.day03_test;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageCache;
import com.android.volley.toolbox.Volley;
public class VolleyTool {
//初始化请求队列、图片加载器
private RequestQueue queue;
private ImageLoader imageLoader;
//私有静态实例
private static VolleyTool instance;
//私有构造方法
private VolleyTool(Context context) {
//创建请求队列
queue = Volley.newRequestQueue(context);
//创建图片加载器
imageLoader = new ImageLoader(queue, new LruImageCache());
}
//公共、静态的方法
public static VolleyTool getInstance(Context context) {
if (instance == null) {
instance = new VolleyTool(context);
}
return instance;
}
//得到请求队列
public RequestQueue getQueue() {
return queue;
}
//得到图片加载器
public ImageLoader getImageLoader() {
return imageLoader;
}
/**
* 使用LRU回收算法的缓存类
*/
class LruImageCache implements ImageCache {
// 缓存容器
private LruCache<String, Bitmap> cache;
public LruImageCache() {
// 计算缓存的最值
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
//创建缓存对象实例
cache = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
// 返回bitmap占用的内存大小
return value.getRowBytes() * value.getHeight();
}
};
}
// 从缓存中取图片对象
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
// 将图片对象保存到缓存容器中
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
}
}
MainActivity.javapackage com.atguigu.day03_test;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.StringRequest;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
public class MainActivity extends Activity {
// 进度条
private ProgressBar pb_main;
// 请求队列
RequestQueue requestQueue;
// 显示存放服务端数据的listView
private PullToRefreshListView lv_main;
// 数据对象集合
private List<ShopInfo> data = new ArrayList<ShopInfo>();
// 适配器
private MainAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 定义的PullToRefreshListView需要转型
lv_main = (PullToRefreshListView) findViewById(R.id.lv_main);
// 下拉刷新的监听
lv_main.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {
@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
//定义一个标示,如果为true,代表下拉
loadData(true);
}
});
// 上拉加载的刷新
lv_main.setOnLastItemVisibleListener(new PullToRefreshBase.OnLastItemVisibleListener() {
@Override
public void onLastItemVisible() {
// pb_foot.isShown()说明数据没有加载完毕
if (pb_foot.isShown()) {
//定义一个标示,如果为false,代表上拉
loadData(false);
}
}
});
// 创建进度条对象
pb_main = (ProgressBar) findViewById(R.id.pb_main);
// 得到请求队列
requestQueue = VolleyTool.getInstance(getApplicationContext())
.getQueue();
// 添加一个footView(上拉松开加载)
addFootView();
// 初始化加载数据显示(false或者true均可)
loadData(false);
}
/**
* 添加一个footView 1. 如果还有更多数据, 它就会显示 2. 如果没有更多数据: 隐藏ProgressBar, 更新TextView的文本
*/
private ProgressBar pb_foot;
private TextView tv_foot;
private void addFootView() {
View footView = View.inflate(this, R.layout.listview_foot, null);
pb_foot = (ProgressBar) footView.findViewById(R.id.pb_foot);
tv_foot = (TextView) footView.findViewById(R.id.tv_foot);
lv_main.getRefreshableView().addFooterView(footView);
}
/*
* 页面上下滑动,如果还没有加载完毕,就快速滑动过去
* 这样消耗内存 定义一个标记,标记的意思是--某次请求是否正在加载图片(默认没有加载,表明已经加载过)
*/
private boolean loading = false;
private void loadData(final boolean reset) {
/*
* 如果正在加载,直接结束,从新滑到的图片无需继续加载了
*/
if (loading)
return;
// 一旦方法执行,就将标记改成true,说明正在加载
loading = true;
// 计算start-如果加载第一页就是0,如果不是第一页就是data.size
int start = reset ? 0 : data.size();
// data.size()==10 -->start=10
String url = "http://192.168.30.41:8090/dianpin_03/ShopListServlet?start="
+ start + "&count=5";
// 创建一个请求
Request request = new StringRequest(url, new Listener<String>() {
@Override
public void onResponse(String response) {
/*
* 从服务器得到数据,一旦该方法触发,说明某次请求已经加载完毕图片了 要将标记改为false,说明已经加载完毕,无需加载了
*/
loading = false;
/*
* 即使加载完毕,如果继续往下拉的话,还会发送请求 这里需要判断服务器端返回null值的情况(查看服务端代码)
*/
if ("".equals(response)) {
// 隐藏ProgressBar, 更新TextView的文本
pb_foot.setVisibility(View.GONE);
tv_foot.setText("已加载完部数据");
// 将该方法直接返回,无需继续往下执行了
return;
}
// 将服务器端的json数组解析为ShopInfo对象集合
List<ShopInfo> newData = new Gson().fromJson(response,
new TypeToken<List<ShopInfo>>() {
}.getType());
// 因为每次请求5个json对象,如果返回小于5说明已经加载完所有的数据了
if (newData.size() < 5) {
// 隐藏ProgressBar, 更新TextView的文本
pb_foot.setVisibility(View.GONE);
tv_foot.setText("已加载完部数据");
}
/*
* 第一次加载 lv_main.setAdapter(adapter);
* 说明只显示第一页的数据
*/
if (adapter == null) {
data = newData;
adapter = new MainAdapter();
lv_main.setAdapter(adapter);
pb_main.setVisibility(View.GONE);
} else {
if (reset) {
// 如果适配器不为null,并且下拉刷新,需要清空数据,只加载第一页
data.clear();
// 显示加载更多
pb_foot.setVisibility(View.VISIBLE);
tv_foot.setText("下拉加载更多");
lv_main.onRefreshComplete();
}
// 不是第一次加载,就需要将每次获取的数据放到data集合中
data.addAll(newData);
adapter.notifyDataSetChanged();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "请求服务器异常", 0).show();
}
});
// 将请求添加到队列中, 自动处理
requestQueue.add(request);
}
/**
* 适配器代码
*/
class MainAdapter extends BaseAdapter {
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(getApplicationContext(),
R.layout.list_item, null);
holder.imageView = (NetworkImageView) convertView
.findViewById(R.id.iv_img);
holder.textView = (TextView) convertView
.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ShopInfo shopInfo = data.get(position);
holder.textView.setText(shopInfo.getName());
// 设置未加载默认图片
holder.imageView.setDefaultImageResId(R.drawable.default_icon);
// 设置加载异常的图片
holder.imageView.setErrorImageResId(R.drawable.error);
// 动态加载图片
String url = "http://192.168.30.41:8090/dianpin_03/image/"
+ shopInfo.getImg();
holder.imageView.setImageUrl(url,
VolleyTool.getInstance(getApplicationContext())
.getImageLoader());
return convertView;
}
class ViewHolder {
NetworkImageView imageView;
TextView textView;
}
}
}
PullToRefreshListView进阶(五)----->上下刷新、上拉加载
标签:
原文地址:http://blog.csdn.net/u013210620/article/details/48006251