1 package com.lixu.listviewrefresh; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.Random; 6 7 import com.lixu.listviewrefresh.Loadnetimage.OnLoadnetimageListener; 8 import com.lixu.listviewrefresh.MyRefreshListview.OnRefreshListener; 9 import android.annotation.SuppressLint; 10 import android.app.Activity; 11 import android.app.ProgressDialog; 12 import android.content.Context; 13 import android.graphics.Bitmap; 14 import android.graphics.BitmapFactory; 15 import android.os.AsyncTask; 16 import android.os.Bundle; 17 import android.util.Log; 18 import android.view.LayoutInflater; 19 import android.view.View; 20 import android.view.ViewGroup; 21 import android.widget.ArrayAdapter; 22 import android.widget.ImageView; 23 import android.widget.ListView; 24 import android.widget.TextView; 25 26 public class MainActivity extends Activity { 27 private static final String KEY_IMAGE = "image_key"; 28 private static final String KEY_TEXT = "text_key"; 29 30 private static final String CACHE_KEY_IMAGE = "cache_image_key"; 31 private static final String CACHE_KEY_TEXT = "cache_text_key"; 32 // 原始数据 33 private ArrayList<HashMap<String, Object>> data; 34 // 缓存队列 35 private ArrayList<HashMap<String, Object>> cache; 36 37 private ArrayAdapter<String> mMyAdapter; 38 39 private MyRefreshListview lv; 40 41 private Activity activity; 42 private Random random = new Random(); 43 // 图片网络地址 44 private String[] image_urls = { "http://img0.bdstatic.com/img/image/shouye/mxh007.jpg", 45 "http://f.hiphotos.baidu.com/image/h%3D360/sign=1c9a50843ec79f3d90e1e2368aa0cdbc/f636afc379310a5566becb8fb24543a982261036.jpg", 46 "http://h.hiphotos.baidu.com/image/h%3D360/sign=04ef437b0b23dd543e73a16ee108b3df/50da81cb39dbb6fd9d9ada390b24ab18962b37ef.jpg", 47 "http://b.hiphotos.baidu.com/image/h%3D360/sign=e91921f7c1fdfc03fa78e5bee43e87a9/8b82b9014a90f60352684b4e3b12b31bb151eddb.jpg", 48 "http://g.hiphotos.baidu.com/image/h%3D360/sign=a2540bdbf21f3a2945c8d3c8a925bce3/fd039245d688d43fa9943bf77f1ed21b0ef43bf1.jpg", 49 "http://p4.so.qhimg.com/bdr/_240_/t01d4c378e7c6bfbe69.jpg", 50 "http://p0.so.qhimg.com/bdr/_240_/t0160872a7d33df5735.jpg", 51 "http://p3.so.qhimg.com/bdr/_240_/t01473a131702c357dd.jpg" }; 52 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 setContentView(R.layout.activity_main); 57 58 activity = this; 59 60 data = new ArrayList<HashMap<String, Object>>(); 61 cache = new ArrayList<HashMap<String, Object>>(); 62 // 添加初始数据 63 for (int i = 0; i < 30; i++) { 64 HashMap<String, Object> map = new HashMap<String, Object>(); 65 map.put(KEY_IMAGE, BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)); 66 map.put(KEY_TEXT, i); 67 data.add(map); 68 } 69 70 lv = (MyRefreshListview) findViewById(R.id.listview); 71 72 mMyAdapter = new MyAdapter(this, -1); 73 74 lv.setAdapter(mMyAdapter); 75 76 lv.setOnRefreshListener(new OnRefreshListener() { 77 78 @Override 79 public void ontop() { 80 // 随机加入一张图片 81 adddata(image_urls[random.nextInt(8)]); 82 83 } 84 85 @Override 86 public void onbuttom() { 87 // 没有设置缓存机制 88 new MyAsyncTaskBottom(image_urls[random.nextInt(8)]).execute(); 89 } 90 }); 91 } 92 93 private class MyAdapter extends ArrayAdapter<String> { 94 private LayoutInflater flater; 95 private Context context; 96 97 public MyAdapter(Context context, int resource) { 98 99 super(context, resource);100 this.context = context;101 flater = LayoutInflater.from(context);102 103 }104 105 @Override106 public int getCount() {107 return data.size();108 }109 110 @SuppressLint("InflateParams")111 @Override112 public View getView(int position, View convertView, ViewGroup parent) {113 114 if (convertView == null)115 convertView = flater.inflate(R.layout.list, null);116 117 ImageView iv = (ImageView) convertView.findViewById(R.id.image);118 119 iv.setImageBitmap((Bitmap) data.get(position).get(KEY_IMAGE));120 121 TextView tv = (TextView) convertView.findViewById(R.id.text);122 123 tv.setText(position + "原始数据");124 125 return convertView;126 }127 128 }129 130 private class MyAsyncTaskTop extends AsyncTask {131 private ProgressDialog pd;132 @SuppressWarnings("unused")133 private String url;134 135 public MyAsyncTaskTop(String url) {136 this.url = url;137 }138 139 @Override140 protected void onPreExecute() {141 // 设置加载进度条142 pd = new ProgressDialog(activity);143 pd.setProgressStyle(pd.STYLE_HORIZONTAL);144 pd.setMessage("正在加载。。。");145 pd.show();146 }147 148 @Override149 protected Object doInBackground(Object... params) {150 151 try {152 // 回调加载网络的类Loadnetimage153 Loadnetimage mLoadnetimage = new Loadnetimage();154 155 mLoadnetimage.SetLoadnetimageListener(new OnLoadnetimageListener() {156 157 @SuppressWarnings("unchecked")158 @Override159 public void LoadnetimageListener(int count, int total) {160 publishProgress(count, total);161 162 }163 });164 // 获取网络图片165 Bitmap bitmap = mLoadnetimage.loadRawDataFromURL(url);166 // 每次将图片和对应的地址放入HashMap167 HashMap<String, Object> map = new HashMap<String, Object>();168 // 将新加载图片放入缓存169 map.put(CACHE_KEY_IMAGE, bitmap);170 map.put(CACHE_KEY_TEXT, url);171 172 cache.add(map);173 174 return bitmap;175 } catch (Exception e) {176 e.printStackTrace();177 }178 179 return null;180 181 }182 183 @Override184 protected void onPostExecute(Object result) {185 addtop(result);186 pd.dismiss();187 188 }189 190 // 更新进度条191 @Override192 protected void onProgressUpdate(Object... values) {193 int count = (Integer) values[0];194 int total = (Integer) values[1];195 196 pd.setMax(total);197 pd.setProgress(count);198 199 }200 201 }202 203 @SuppressWarnings("unused")204 private class MyAsyncTaskBottom extends AsyncTask {205 private ProgressDialog pd;206 private String url;207 208 public MyAsyncTaskBottom(String url) {209 this.url = url;210 }211 212 @Override213 protected void onPreExecute() {214 // 设置进度条215 pd = new ProgressDialog(activity);216 // 样式217 pd.setProgressStyle(pd.STYLE_HORIZONTAL);218 pd.setMessage("正在加载。。。");219 pd.show();220 221 }222 223 @Override224 protected Object doInBackground(Object... params) {225 // 回调加载网络的类Loadnetimage226 Loadnetimage mLoadnetimage = new Loadnetimage();227 // 获取网络图片228 Bitmap bitmap;229 try {230 bitmap = mLoadnetimage.loadRawDataFromURL(url);231 return bitmap;232 } catch (Exception e) {233 e.printStackTrace();234 }235 return null;236 }237 238 @Override239 protected void onPostExecute(Object result) {240 addbottom(result);241 pd.dismiss();242 243 }244 245 }246 247 private void adddata(String url) {248 // 设置缓存机制249 Log.e("", "开始添加");250 251 for (int i = 0; i < cache.size(); i++) {252 253 HashMap<String, Object> map = cache.get(i);254 // 判断图片地址一样则载入缓存255 if (url.equals(map.get(CACHE_KEY_TEXT))) {256 Bitmap bitmap = (Bitmap) map.get(CACHE_KEY_IMAGE);257 addtop(bitmap);258 Log.e("", "载入缓存");259 260 return;261 }262 263 }264 // 否则从网络新加载265 Log.e("", "最新加载");266 new MyAsyncTaskTop(url).execute();267 268 }269 270 private void addtop(Object result) {271 272 // 新加载图片放入原始数据273 HashMap<String, Object> map = new HashMap<String, Object>();274 map.put(KEY_IMAGE, result);275 map.put(KEY_TEXT, data.size() + 1);276 277 data.add(0, map);278 279 mMyAdapter.notifyDataSetChanged();280 }281 282 private void addbottom(Object result) {283 HashMap<String, Object> map = new HashMap<String, Object>();284 map.put(KEY_IMAGE, result);285 map.put(KEY_TEXT, data.size() + 1);286 287 data.add(map);288 289 mMyAdapter.notifyDataSetChanged();290 // 添加数据后自动滚动到底部291 lv.setSelection(ListView.FOCUS_DOWN);292 293 }294 295 }
1 package com.lixu.listviewrefresh; 2 3 import java.io.BufferedInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.InputStream; 6 import java.net.HttpURLConnection; 7 import java.net.URL; 8 9 import android.graphics.Bitmap;10 import android.graphics.BitmapFactory;11 12 public class Loadnetimage {13 // 设置回调机制14 15 private OnLoadnetimageListener mOnLoadnetimageListener;16 17 public Loadnetimage() {18 19 }20 21 public interface OnLoadnetimageListener {22 public void LoadnetimageListener(int count, int total);23 }24 25 public void SetLoadnetimageListener(OnLoadnetimageListener l) {26 mOnLoadnetimageListener = l;27 }28 29 30 31 public Bitmap loadRawDataFromURL(String u) throws Exception {32 33 URL url = new URL(u);34 HttpURLConnection conn = (HttpURLConnection) url.openConnection();35 // 设置请求的一些常用的参数36 conn.setReadTimeout(30000);37 conn.setConnectTimeout(30000);38 conn.setDoInput(true);39 conn.connect();40 // 获取图片总数41 int total = conn.getContentLength();42 43 InputStream is = conn.getInputStream();44 BufferedInputStream bis = new BufferedInputStream(is);45 46 ByteArrayOutputStream baos = new ByteArrayOutputStream();47 // 缓存2KB48 final int BUFFER_SIZE = 2 * 1024;49 final int EOF = -1;50 51 int count = 0;52 53 int c;54 byte[] buf = new byte[BUFFER_SIZE];55 56 while (true) {57 c = bis.read(buf);58 if (c == EOF)59 break;60 // 每次累加到现在为止我们下载了多少数据,以便于后面计算已经下载的数据占了总数量的百分比61 count = count + c;62 // 发布最新的数据,更新随后的进度条显示进度使用63 if (mOnLoadnetimageListener != null)64 mOnLoadnetimageListener.LoadnetimageListener(count, total);65 baos.write(buf, 0, c);66 }67 68 conn.disconnect();69 is.close();70 71 byte[] data = baos.toByteArray();72 baos.flush();73 74 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);75 76 return bitmap;77 }78 79 }
1 package com.lixu.listviewrefresh; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.GestureDetector; 6 import android.view.MotionEvent; 7 import android.view.View; 8 import android.widget.AbsListView; 9 import android.widget.ListView;10 11 public class MyRefreshListview extends ListView {12 private OnRefreshListener mOnRefreshListener;13 private Context context;14 private int firstVisibleItem, visibleItemCount, totalItemCount;15 16 public MyRefreshListview(Context context, AttributeSet attrs) {17 super(context, attrs);18 this.context = context;19 20 }21 22 public interface OnRefreshListener {23 24 public void ontop();25 26 public void onbuttom();27 }28 29 public void setOnRefreshListener(OnRefreshListener l) {30 this.mOnRefreshListener = l;31 // 这个方法可以解决当listview中初始没有数据的时候滑动来加载数据32 final GestureDetector mGestureDetector = new GestureDetector(context,33 new GestureDetector.SimpleOnGestureListener() {34 35 // velocityY表示触摸停止点Y到触摸起始点Y的速度值 当两点距离值为负时,速度值也为负所以:36 // >0表示从上往下拉37 // <0表示从下往上拉38 public boolean onFling(android.view.MotionEvent e1, android.view.MotionEvent e2, float velocityX,39 float velocityY) {40 if (velocityY > 0) {41 42 // 滑动到顶部时添加43 if (firstVisibleItem == 0) {44 45 mOnRefreshListener.ontop();46 47 }48 49 }50 if (velocityY < 0) {51 // 滑动到底部时添加52 if ((firstVisibleItem + visibleItemCount) == totalItemCount) {53 54 mOnRefreshListener.onbuttom();55 56 }57 }58 59 return super.onFling(e1, e2, velocityX, velocityY);60 };61 62 });63 this.setOnTouchListener(new OnTouchListener() {64 // 将触摸事件交给GestureDetector来处理65 @Override66 public boolean onTouch(View v, MotionEvent event) {67 68 return mGestureDetector.onTouchEvent(event);69 }70 });71 72 this.setOnScrollListener(new OnScrollListener() {73 74 @Override75 public void onScrollStateChanged(AbsListView view, int scrollState) {76 77 }78 79 @Override80 public void onScroll(AbsListView view, int fvi, int vic, int tic) {81 82 firstVisibleItem = fvi;83 visibleItemCount = vic;84 totalItemCount = tic;85 86 }87 });88 89 }90 91 }
xml文件:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context="com.lixu.listviewrefresh.MainActivity" > 6 7 <com.lixu.listviewrefresh.MyRefreshListview 8 android:id="@+id/listview" 9 android:layout_width="match_parent"10 android:layout_height="match_parent" />11 12 </RelativeLayout>
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="match_parent" 5 android:orientation="vertical" > 6 7 <ImageView 8 android:id="@+id/image" 9 android:layout_width="match_parent"10 android:layout_height="match_parent" />11 12 <TextView13 android:id="@+id/text"14 android:layout_width="match_parent"15 android:layout_height="match_parent" />16 17 </LinearLayout>
运行效果图: