PullToRefreshListView进阶(五)----->上下刷新、上拉加载

依赖库:

先看服务端的代码(对象封装类和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));
			}
		}
	}
}

--------------------------------------------分割线-------------------------------------------------------------------

看android代码

先贴出布局来

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.java

package 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;
		}
	}
}
时间: 2024-10-14 16:54:42

PullToRefreshListView进阶(五)----->上下刷新、上拉加载的相关文章

带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载

转载请注明出处:http://blog.csdn.net/lowprofile_coding/article/details/51321896 一 .前言 最近实在太忙,一个多礼拜没有更新文章了,于是今晚加班加点把demo写出来,现在都12点了才开始写文章. 1.我们的目标 把RecyclerView下拉刷新上拉加载更多加入到我们的开发者头条APP中. 2.效果图 3.实现步骤 找一个带上拉刷新下载加载更多的RecyclerView开源库,我们要站在巨人的肩膀上 下载下来自己先运行下demo,然

Android 下拉刷新上拉加载效果功能,使用开源项目android-pulltorefresh实现

应用场景: 在App开发中,对于信息的获取与演示,不可能全部将其获取与演示,为了在用户使用中,给予用户以友好.方便的用户体验,以滑动.下拉的效果动态加载数据的要求就会出现.为此,该效果功能就需要应用到所需要的展示页面中. 知识点介绍: 本文主要根据开源项目android-pulltorefresh展开介绍. android-pulltorefresh [一个强大的拉动刷新开源项目,支持各种控件下拉刷新 ListView.ViewPager.WevView.ExpandableListView.G

自个儿写Android的下拉刷新/上拉加载控件 (续)

本文算是对之前的一篇博文<自个儿写Android的下拉刷新/上拉加载控件>的续章,如果有兴趣了解更多的朋友可以先看一看之前的这篇博客. 事实上之所以会有之前的那篇博文的出现,是起因于前段时间自己在写一个练手的App时很快就遇到这种需求.其实我们可以发现类似这样下拉刷新.上拉加载的功能正在变得越来越普遍,可以说如今基本上绝大多数的应用里面都会使用到.当然,随着Android的发展,已经有不少现成的可以实现这种需求的"轮子"供我们使用了. 但转过头想一下想,既然本来就是自己练手

Android 下拉刷新上拉加载效果功能

应用场景: 在App开发中,对于信息的获取与演示,不可能全部将其获取与演示,为了在用户使用中,给予用户以友好.方便的用户体验,以滑动.下拉的效果动态加载数据的要求就会出现.为此,该效果功能就需要应用到所需要的展示页面中. 知识点介绍: 本文主要根据开源项目android-pulltorefresh展开介绍. android-pulltorefresh [一个强大的拉动刷新开源项目,支持各种控件下拉刷新 ListView.ViewPager.WevView.ExpandableListView.G

android 下拉刷新/上拉加载更多【pull-to-refresh】

这两天在做一个功能,需要用到"下拉刷新和上拉加载更多"这样的功能,开始的时候以为都是自己用控件加以控件来完成的,后来,在网上找了好长时间,发现直接可以用别人的现在的 library . 引用别人的library后直接就可以用的,只是注意一些细节就可以了. 我用的是pull to refresh (很多人都说这个比较好点). 它支持多种常用的需要刷新的View类型,如:ListView.ExpandableListView.GridView.WebView等.这里就给个下载地址吧:htt

Android-PullToRefresh下拉刷新,上拉加载的使用详解

哎,最近事真的是多.没有坚持写博客虽然写得差,但还是得坚持写嘛!废话不多说,进入今天的主题. 在Android开发中下拉刷新,上拉加载这个功能是一般商业应用的App中必不可少的一个功能效果.但是对于新手来说,自定义下拉刷新的ListView可能还是会遇到很多的问题.而对于要快速开发的公司来说,可能时间又比较紧张.那么这时候我们就要用到一个开源控件Android-PullToRefresh了.这个开源控件是一款非常优秀的开源控件,可以直接从Github上下载下来直接使用.下载链接地址:https:

Android 下拉刷新上拉加载 多种应用场景 超级大放送(上)

转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉加载,网上的Demo太多太多了,这里不是介绍怎么去实现下拉刷新上拉加载,而是针对下拉刷新上拉加载常用的一些应用场景就行了一些总结,包含了下拉刷新上拉加载过程中遇到的一些手势冲突问题的解决方法(只能算是抛砖引玉). 去年9月的时候,那时自己正在独立做Android项目.记得刚刚写完那个ListView列表页面(木有下拉刷新,上拉加载)

android 下拉刷新上拉加载更多,高仿ios左滑动删除item,解决了众多手势问题

一.前言 老规矩,别的不说,这demo是找了很相关知识集合而成的,可以说对我这种小白来说是绞尽脑汁!程序员讲的是无图无真相!现在大家一睹为快! 二.比较关键的还是scroller这个类的 package com.icq.slideview.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; i

使用MJRefresh自定义下拉刷新,上拉加载动画

有时候我们需要自己设置下拉刷新,上拉加载动画的实现,这里主要是记录下使用MJRefresh自定义下拉刷新,上拉加载动画..... 下拉刷新我们只需要继承MJRefreshGifHeader即可: 实现代码如下: - (void)prepare{ [super prepare]; self.stateLabel.hidden = NO; self.lastUpdatedTimeLabel.hidden = YES; [self setImages:@[[UIImage imageNamed:@"v

IOS开发之XML解析以及下拉刷新上拉加载更多的分享

IOS开发之XML解析 1.XML格式 <?xml version="1.0" encoding="utf-8" ?> 表示XML文件版本, 内部文本使用的编码 <root> 表示根节点 <CityName>北京</CityName>  一个结点, CityName是结点名, 北京结点值 <Item key="1" value="A"></Item>