PullToRefreshListView進階(五)----->上下重新整理、上拉載入
阿新 • • 發佈:2019-01-24
依賴庫:
先看服務端的程式碼(物件封裝類和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
list_item.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>
listview_foot.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>
<?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;
}
}
}