自己定制ListView,上拉刷新和下拉刷新,加载网络图片,并且添加缓存机制。
2015-12-18 14:37
609 查看
package com.lixu.listviewrefresh; import java.util.ArrayList; import java.util.HashMap; import java.util.Random; import com.lixu.listviewrefresh.Loadnetimage.OnLoadnetimageListener; import com.lixu.listviewrefresh.MyRefreshListview.OnRefreshListener; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private static final String KEY_IMAGE = "image_key"; private static final String KEY_TEXT = "text_key"; private static final String CACHE_KEY_IMAGE = "cache_image_key"; private static final String CACHE_KEY_TEXT = "cache_text_key"; // 原始数据 private ArrayList<HashMap<String, Object>> data; // 缓存队列 private ArrayList<HashMap<String, Object>> cache; private ArrayAdapter<String> mMyAdapter; private MyRefreshListview lv; private Activity activity; private Random random = new Random(); // 图片网络地址 private String[] image_urls = { "http://img0.bdstatic.com/img/image/shouye/mxh007.jpg", "http://f.hiphotos.baidu.com/image/h%3D360/sign=1c9a50843ec79f3d90e1e2368aa0cdbc/f636afc379310a5566becb8fb24543a982261036.jpg", "http://h.hiphotos.baidu.com/image/h%3D360/sign=04ef437b0b23dd543e73a16ee108b3df/50da81cb39dbb6fd9d9ada390b24ab18962b37ef.jpg", "http://b.hiphotos.baidu.com/image/h%3D360/sign=e91921f7c1fdfc03fa78e5bee43e87a9/8b82b9014a90f60352684b4e3b12b31bb151eddb.jpg", "http://g.hiphotos.baidu.com/image/h%3D360/sign=a2540bdbf21f3a2945c8d3c8a925bce3/fd039245d688d43fa9943bf77f1ed21b0ef43bf1.jpg", "http://p4.so.qhimg.com/bdr/_240_/t01d4c378e7c6bfbe69.jpg", "http://p0.so.qhimg.com/bdr/_240_/t0160872a7d33df5735.jpg", "http://p3.so.qhimg.com/bdr/_240_/t01473a131702c357dd.jpg" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; data = new ArrayList<HashMap<String, Object>>(); cache = new ArrayList<HashMap<String, Object>>(); // 添加初始数据 for (int i = 0; i < 30; i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put(KEY_IMAGE, BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)); map.put(KEY_TEXT, i); data.add(map); } lv = (MyRefreshListview) findViewById(R.id.listview); mMyAdapter = new MyAdapter(this, -1); lv.setAdapter(mMyAdapter); lv.setOnRefreshListener(new OnRefreshListener() { @Override public void ontop() { // 随机加入一张图片 adddata(image_urls[random.nextInt(8)]); } @Override public void onbuttom() { // 没有设置缓存机制 new MyAsyncTaskBottom(image_urls[random.nextInt(8)]).execute(); } }); } private class MyAdapter extends ArrayAdapter<String> { private LayoutInflater flater; private Context context; public MyAdapter(Context context, int resource) { super(context, resource); this.context = context; flater = LayoutInflater.from(context); } @Override public int getCount() { return data.size(); } @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) convertView = flater.inflate(R.layout.list, null); ImageView iv = (ImageView) convertView.findViewById(R.id.image); iv.setImageBitmap((Bitmap) data.get(position).get(KEY_IMAGE)); TextView tv = (TextView) convertView.findViewById(R.id.text); tv.setText(position + "原始数据"); return convertView; } } private class MyAsyncTaskTop extends AsyncTask { private ProgressDialog pd; @SuppressWarnings("unused") private String url; public MyAsyncTaskTop(String url) { this.url = url; } @Override protected void onPreExecute() { // 设置加载进度条 pd = new ProgressDialog(activity); pd.setProgressStyle(pd.STYLE_HORIZONTAL); pd.setMessage("正在加载。。。"); pd.show(); } @Override protected Object doInBackground(Object... params) { try { // 回调加载网络的类Loadnetimage Loadnetimage mLoadnetimage = new Loadnetimage(); mLoadnetimage.SetLoadnetimageListener(new OnLoadnetimageListener() { @SuppressWarnings("unchecked") @Override public void LoadnetimageListener(int count, int total) { publishProgress(count, total); } }); // 获取网络图片 Bitmap bitmap = mLoadnetimage.loadRawDataFromURL(url); // 每次将图片和对应的地址放入HashMap HashMap<String, Object> map = new HashMap<String, Object>(); // 将新加载图片放入缓存 map.put(CACHE_KEY_IMAGE, bitmap); map.put(CACHE_KEY_TEXT, url); cache.add(map); return bitmap; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Object result) { addtop(result); pd.dismiss(); } // 更新进度条 @Override protected void onProgressUpdate(Object... values) { int count = (Integer) values[0]; int total = (Integer) values[1]; pd.setMax(total); pd.setProgress(count); } } @SuppressWarnings("unused") private class MyAsyncTaskBottom extends AsyncTask { private ProgressDialog pd; private String url; public MyAsyncTaskBottom(String url) { this.url = url; } @Override protected void onPreExecute() { // 设置进度条 pd = new ProgressDialog(activity); // 样式 pd.setProgressStyle(pd.STYLE_HORIZONTAL); pd.setMessage("正在加载。。。"); pd.show(); } @Override protected Object doInBackground(Object... params) { // 回调加载网络的类Loadnetimage Loadnetimage mLoadnetimage = new Loadnetimage(); // 获取网络图片 Bitmap bitmap; try { bitmap = mLoadnetimage.loadRawDataFromURL(url); return bitmap; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Object result) { addbottom(result); pd.dismiss(); } } private void adddata(String url) { // 设置缓存机制 Log.e("", "开始添加"); for (int i = 0; i < cache.size(); i++) { HashMap<String, Object> map = cache.get(i); // 判断图片地址一样则载入缓存 if (url.equals(map.get(CACHE_KEY_TEXT))) { Bitmap bitmap = (Bitmap) map.get(CACHE_KEY_IMAGE); addtop(bitmap); Log.e("", "载入缓存"); return; } } // 否则从网络新加载 Log.e("", "最新加载"); new MyAsyncTaskTop(url).execute(); } private void addtop(Object result) { // 新加载图片放入原始数据 HashMap<String, Object> map = new HashMap<String, Object>(); map.put(KEY_IMAGE, result); map.put(KEY_TEXT, data.size() + 1); data.add(0, map); mMyAdapter.notifyDataSetChanged(); } private void addbottom(Object result) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put(KEY_IMAGE, result); map.put(KEY_TEXT, data.size() + 1); data.add(map); mMyAdapter.notifyDataSetChanged(); // 添加数据后自动滚动到底部 lv.setSelection(ListView.FOCUS_DOWN); } }
package com.lixu.listviewrefresh; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class Loadnetimage { // 设置回调机制 private OnLoadnetimageListener mOnLoadnetimageListener; public Loadnetimage() { } public interface OnLoadnetimageListener { public void LoadnetimageListener(int count, int total); } public void SetLoadnetimageListener(OnLoadnetimageListener l) { mOnLoadnetimageListener = l; } public Bitmap loadRawDataFromURL(String u) throws Exception { URL url = new URL(u); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求的一些常用的参数 conn.setReadTimeout(30000); conn.setConnectTimeout(30000); conn.setDoInput(true); conn.connect(); // 获取图片总数 int total = conn.getContentLength(); InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 缓存2KB final int BUFFER_SIZE = 2 * 1024; final int EOF = -1; int count = 0; int c; byte[] buf = new byte[BUFFER_SIZE]; while (true) { c = bis.read(buf); if (c == EOF) break; // 每次累加到现在为止我们下载了多少数据,以便于后面计算已经下载的数据占了总数量的百分比 count = count + c; // 发布最新的数据,更新随后的进度条显示进度使用 if (mOnLoadnetimageListener != null) mOnLoadnetimageListener.LoadnetimageListener(count, total); baos.write(buf, 0, c); } conn.disconnect(); is.close(); byte[] data = baos.toByteArray(); baos.flush(); Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); return bitmap; } }
package com.lixu.listviewrefresh; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.widget.AbsListView; import android.widget.ListView; public class MyRefreshListview extends ListView { private OnRefreshListener mOnRefreshListener; private Context context; private int firstVisibleItem, visibleItemCount, totalItemCount; public MyRefreshListview(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public interface OnRefreshListener { public void ontop(); public void onbuttom(); } public void setOnRefreshListener(OnRefreshListener l) { this.mOnRefreshListener = l; // 这个方法可以解决当listview中初始没有数据的时候滑动来加载数据 final GestureDetector mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { // velocityY表示触摸停止点Y到触摸起始点Y的速度值 当两点距离值为负时,速度值也为负所以: // >0表示从上往下拉 // <0表示从下往上拉 public boolean onFling(android.view.MotionEvent e1, android.view.MotionEvent e2, float velocityX, float velocityY) { if (velocityY > 0) { // 滑动到顶部时添加 if (firstVisibleItem == 0) { mOnRefreshListener.ontop(); } } if (velocityY < 0) { // 滑动到底部时添加 if ((firstVisibleItem + visibleItemCount) == totalItemCount) { mOnRefreshListener.onbuttom(); } } return super.onFling(e1, e2, velocityX, velocityY); }; }); this.setOnTouchListener(new OnTouchListener() { // 将触摸事件交给GestureDetector来处理 @Override public boolean onTouch(View v, MotionEvent event) { return mGestureDetector.onTouchEvent(event); } }); this.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int fvi, int vic, int tic) { firstVisibleItem = fvi; visibleItemCount = vic; totalItemCount = tic; } }); } }
xml文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.lixu.listviewrefresh.MainActivity" > <com.lixu.listviewrefresh.MyRefreshListview android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
<?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="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
运行效果图:
相关文章推荐
- iOS-----使用CFNetwork实现TCP协议的通信
- Pyhont 网络编程【第一篇】初始Socket网络套接字
- poj 2455 网络流最大值最小值
- BZOJ3931 [CQOI2015] 网络吞吐量
- 基于fiddler插件开发的移动测试网络监控与分析
- HttpUrlConnection 网络请求工具类
- 基于fiddler插件开发的移动测试网络监控与分析
- 在Unity3D的网络游戏中实现资源动态加载
- iOS去除网络请求到的数据的null值
- windows TCP socket在C++下的编程入门 2
- CentOS---网络配置详解
- iOS开发网络篇—多线程断点下载
- 使用Apache HttpClient4.x 发送 GET POST 请求
- php http 缓存(客户端缓存)
- Android Studio 编译不通过,报错“找不到org.apache.http
- Session
- TCP的流量控制和拥塞控制
- 中国自然语言处理开源组织https://github.com/NLPchina
- 简单的缓存代理HTTP服务器
- ios开发如何封装AFN第三方类库中的http请求