private RefreshListView mListView;
private Context mContext;
// 网络图片加载
public List getDatas() {
return mDatas;
}
public void setDatas(List mDatas) {
this.mDatas = mDatas;
}
public void setData(int pos, NewsBean bean) {
if (-1 != pos) {
mDatas.add(pos, bean);
MainActivity.urls.add(pos, bean.NewsPicResUrl);
} else {
mDatas.add(bean);
MainActivity.urls.add(bean.NewsPicResUrl);
}
}
private ImageLoader mImageLoader;
public NewsAdapter(Context context, List mDatas, RefreshListView listView) {
super();
mContext = context;
this.mDatas = mDatas;
this.mInflater = LayoutInflater.from(context);
//抽象成单例后改写 begin
//mImageLoader = new ImageLoader(listView); mImageLoader = ImageLoader.getInstance(context);
mImageLoader.setmListView(listView);
//抽象成单例后改写 end
mListView = listView;
initHeaderView();
initFooterView();
}
private void initFooterView() {
mFooterView = mListView.getFooterView();
}
//下拉刷新数据
public void onDateChange(List mDatas) {
this.mDatas = mDatas;
this.notifyDataSetChanged();
}
//下拉刷新数据
private void initHeaderView() {
headerView = mListView.findViewById(R.id.headerview);
// 获取View高度
headerHeight = mListView.getHeaderHeight();
mTipView = (TextView) headerView.findViewById(R.id.tip);
mTimeView = (TextView) headerView.findViewById(R.id.lastupdate_time);
mArrowView = (ImageView) headerView.findViewById(R.id.arrow);
mBar = (ProgressBar) headerView.findViewById(R.id.progress);
}
@Override
public int getCount() {
if (mDatas != null)
return mDatas.size();
return 0;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
//Log.i(TAG, “getView->缓存为空:” + position);
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, parent, false);
holder.pic = (ImageView) convertView.findViewById(R.id.iv_pic);
holder.no = (TextView) convertView.findViewById(R.id.tv_no);
holder.name = (TextView) convertView.findViewById(R.id.tv_name);
holder.description = (TextView) convertView
.findViewById(R.id.tv_description);
convertView.setTag(holder);
} else {
//Log.i(TAG, “getView->缓存过:” + position);
holder = (ViewHolder) convertView.getTag();
}
NewsBean bean = mDatas.get(position);
// 加载网络图片
holder.pic.setTag(bean.NewsPicResUrl);
// mImageLoader.getImageByAsyncTask(holder.pic, bean.NewsPicResUrl);
holder.pic.setImageResource(R.drawable.ic_launcher);
// 滑动优化 如果有缓存,则加载 否则不加载
final Bitmap pBitmap = mImageLoader.setDefaultBitmap(holder.pic, bean.NewsPicResUrl);
// /滑动优化
holder.name.setText(bean.NewsName);
holder.description.setText(bean.NewsDescription);
holder.no.setText(bean.NewsNo);
//添加事件点击 2015 12 24
final String urlBig = bean.NewsPicBigResUrl;
final String urlSmall = bean.NewsPicResUrl;
holder.pic.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), “bean.NewsNo:” + urlBig, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(mContext, BigImageActivity.class);
intent.putExtra(“urlBig”, urlBig);
intent.putExtra(“urlSmall”, urlSmall);
mContext.startActivity(intent);
}
});
//
return convertView;
}
class ViewHolder {
public ImageView pic;
public TextView name;
public TextView description;
public TextView no;
}
// 滚动时的优化 begin
private int mStart, mEnd;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
Log.i(TAG, “scrollState:” + mStart + “-” + mEnd);
loadImages();
} else {
Log.i(TAG, “scrollState cancel:”);
mImageLoader.cancelAllTasks();
}
}
private void loadImages() {
if (null != mDatas && mDatas.size() > 0) {
//修复bug 滑动时边缘不加载 begin
int start = mStart != 0 ? mStart - 1 : 0;
int end = mEnd != mDatas.size() ? mEnd + 1 : mEnd;
//修复bug 滑动时边缘不加载 end
mImageLoader.loadImages(start, end);
}
}
private boolean isInit = true;
//加载更多 begin
private boolean isLoading = false;
private View mFooterView;
public interface IOnScrollBottomListener {
void onScrollBottom();
}
private IOnScrollBottomListener mIOnScrollBottomListener;
public void setIOnScrollBottomListener(IOnScrollBottomListener onScrollBottomListener) {
mIOnScrollBottomListener = onScrollBottomListener;
}
public void bottomDataLoadComplete() {
//隐藏view 加载数据 改变flag
mFooterView.setVisibility(View.GONE);
isLoading = false;
}
//加载更多 end
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
Log.i(TAG, “onScroll():totalItemCount” + totalItemCount + " ,isLoading:" + isLoading + “, firstVisibleItem:”
+ firstVisibleItem + " ,visibleItemCount:" + visibleItemCount + “, totalItemCount:” + totalItemCount);
mStart = firstVisibleItem;
//其实现在的listview看不到那么多 应该-1 否则最后会空指针 2015 12 24 (因为我们add了一个headerview进去) 20151228 add 了 footview 所以再-1
mEnd = mStart + visibleItemCount - 1 - 1;
if (visibleItemCount != 0 && isInit) {
isInit = false;
loadImages();
}
//处理滑动加载更多: 2 != totalItemCount 防止没有数据一直在加载更多
if (2 != totalItemCount && firstVisibleItem + visibleItemCount == totalItemCount && !isLoading) {
isLoading = true;
mFooterView.setVisibility(View.VISIBLE);
//执行加载更多操作
if (null != mIOnScrollBottomListener) {
mIOnScrollBottomListener.onScrollBottom();
}
}
}
// 滚动时的优化 end
// 处理下拉刷新 private int lastY;
private View headerView;
private TextView mTipView;
private TextView mTimeView;
private ImageView mArrowView;
private ProgressBar mBar;
private int headerHeight;
private int gap;
public interface IRefereshListener {
public void onRefresh();
}
private IRefereshListener mRefereshListener;
public void setIRefereshListener(IRefereshListener listener) {
this.mRefereshListener = listener;
}
//监听执行完毕 继续滚动
public void refreshComplete(int length) {
Log.i(TAG, “refreshComplete()”);
//其实这里的mStarat =0的
mImageLoader.loadImages(mStart, mStart + length);
rollToInit(1);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mStart == 0 && isMoveEnable) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = (int) event.getY();
//初始化 几个view的状态显示
mTipView.setText(“下拉可以刷新”);
mArrowView.setVisibility(View.VISIBLE);
mBar.setVisibility(View.GONE);
//初始化 几个view的状态显示
break;
case MotionEvent.ACTION_MOVE:
gap = (int) (event.getY() - lastY);
Log.i(TAG, " ACTION_MOVE gap:" + gap);
//移动View
setPaddingTop(-headerHeight + gap);
//下拉可以刷新(超过宽度)-》松开可以刷新-》
if (gap > headerHeight) {
mTipView.setText(“松开可以刷新”);
}
//下拉可以刷新(超过宽度)-》松开可以刷新-》
break;
case MotionEvent.ACTION_UP:
//松开-》滑动到View宽度-》
if (gap > headerHeight) {
rollToInit(0);
//正在刷新-》
mTipView.setText(“正在刷新”);
mArrowView.setVisibility(View.GONE);
mBar.setVisibility(View.VISIBLE);
//执行刷新操作
if (mRefereshListener != null) {
mRefereshListener.onRefresh();
}
//执行刷新操作
//松开-》滑动到View宽度-》 } else {
//恢复初始。
rollToInit(1);
}
break;
default:
break;
}
Log.i(TAG, “lastY:” + lastY + “headerHeight:” + headerHeight);
}
return false;
}
private boolean isMoveEnable = true;
private void rollToInit(int endTop) {
//回去的动画://使用ObjectAnimator 不好实现, 打算用ValueAnimator
/*ObjectAnimator animator = ObjectAnimator.ofFloat(mListView, “Y”,-(headerView.getPaddingTop()+headerHeight)); animator.setDuration(500).start();*/ isMoveEnable = false;
int top = headerView.getPaddingTop();
//解决 拖动不超过headerheight 不会滑动回去的bug
int end = top > 0 ? -(top + headerHeight) : -(top + headerHeight + headerHeight);
Log.i(TAG, “rollToInit:” + endTop + " ,top:" + top + ", -(top+headerHeight) " + (-(top + headerHeight)));
ValueAnimator animator = ValueAnimator.ofInt(top, endTop == 1 ? end : endTop);
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer paddingTop = (Integer) animation.getAnimatedValue();
setPaddingTop(paddingTop);
}
});
//添加动画完成监听器
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
isMoveEnable = true;
}
});
//添加动画完成监听器
animator.setDuration(500).start();
}
private void setPaddingTop(int top) {
if (null != headerView) {
headerView.setPadding(headerView.getPaddingLeft(), top, headerView.getPaddingRight(), headerView.getPaddingBottom());
}
}
}
package com.example.asynctaskdemo;
public class NewsBean {
public String NewsPicResUrl;
public String NewsPicBigResUrl;
public String NewsName;
public String NewsDescription;
public String NewsNo;
}
package com.example.asynctaskdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class RefreshListView extends android.widget.ListView {
private final static String TAG =“zxt/refreshListView”;
private View headerView ;
private View footerView;
public View getFooterView() {
return footerView;
}
/*public void bottomDataLoadComplete(){
//隐藏view 加载数据 改变flag footerView.setVisibility(View.GONE); }*/
private int headerHeight;
public int getHeaderHeight() {
return headerHeight;
}
public RefreshListView(Context context) {
this(context, null);
}
public RefreshListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
headerView = LayoutInflater.from(context).inflate(R.layout.header,null);
this.addHeaderView(headerView);
// 测量View
headerView.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// 获取View高度
headerHeight = headerView.getMeasuredHeight();
Log.d(TAG, “headerHeight:”+headerHeight);
//设置默认隐藏
setPaddingTop(-headerHeight);
//上啦刷新
View footerView = LayoutInflater.from(context).inflate(R.layout.footer_layout,this,false);
this.addFooterView(footerView);
this.footerView = footerView.findViewById(R.id.load_layout);
this.footerView.setVisibility(View.GONE);
}
private void setPaddingTop(int top){
if(null!=headerView){
headerView.setPadding(headerView.getPaddingLeft(), top, headerView.getPaddingRight(), headerView.getPaddingBottom());
}
}
}
package com.example.asynctaskdemo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import com.example.asynctaskdemo.com.mcxtzhang.utils.FileUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import libcore.io.DiskLruCache;
public class ImageLoader {
private static final String TAG = “zxt/ImageLoader”;
//抽象成单例 begin
private static class ImageLoaderHolder {
private static final ImageLoader mImageLoader = new ImageLoader();
}
private static Context mContext;
public static ImageLoader getInstance(Context context){
mContext = context.getApplicationContext();
return ImageLoaderHolder.mImageLoader;
}
private ImageLoader() {
super();
Log.i(“TAG”,“ImageLoader”);
int maxMemory = (int) Runtime.getRuntime().maxMemory();
mCache = new LruCache<String, Bitmap>(maxMemory / 20) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
//硬盘缓存 begin
//初始化工作 File cacheDir = FileUtils.getFileCache(mContext, “disk_caches”);
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
try {
mDiskCache = DiskLruCache.open(cacheDir, 1, 1, 10 * 1024 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
//硬盘缓存 end
mSets = new HashSet();
}
//抽象成单例 end
//图片缓存 start private LruCache<String,Bitmap> mCache;
//硬盘缓存
private DiskLruCache mDiskCache;
public Bitmap getBitmapFromCache(String url){
Log.i(TAG, “getBitmapFromCache”);
return mCache.get(url);
}
public void putBitmapToCache(String url,Bitmap bitmap){
Log.i(TAG, “putBitmapToCache”);
if(null == getBitmapFromCache(url)){
mCache.put(url, bitmap);
}
}
//图片缓存 end
public void getImageByAsyncTask(ImageView imageView,String url){
//图片缓存 start
Bitmap bitmap = getBitmapFromCache(url);
if(null == bitmap)
{
new NewsImageAsyncTask(/*imageView,*/url).execute();
}
else{
imageView.setImageBitmap(bitmap);
}
//图片缓存 end
}
//每次加载一张图片
private class NewsImageAsyncTask extends AsyncTask<Void,Void,Bitmap>{
//private ImageView mImageView ;
private String mUrl;
public NewsImageAsyncTask(/*ImageView mImageView,*/String url) {
super();
//this.mImageView = mImageView;
mUrl = url;
}
@Override
protected Bitmap doInBackground(Void… params) {
//硬盘缓存
// 用了二级缓存 所以要改写获取图片的流程: /*Bitmap result = getBitmapByUrl(mUrl); Log.i(TAG, “isCancelled:”+isCancelled()); //内存缓存 start putBitmapToCache(mUrl, result); //内存缓存end*/ return getBitmapAndSaveToCacheByUrl(mUrl);
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
//设置图片 防止错位
/*if(mUrl.equals(mImageView.getTag())){ mImageView.setImageBitmap(result); }*/ //滑动优化 ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
if(imageView!=null && null != result)
{
imageView.setImageBitmap(result);
}
mSets.remove(this);
//滑动优化
}
}
public Bitmap getBitmapByUrl(String string) {
InputStream is1=null/*,is2 = null*/;
Bitmap result = null;
try {
HttpURLConnection conn = (HttpURLConnection) new URL(string).openConnection();
is1 = new BufferedInputStream(conn.getInputStream());
//优化图片加载 begin
/*ByteArrayOutputStream out = new ByteArrayOutputStream(); ImageUtils.copy(is1,out); is2 = new ByteArrayInputStream(out.toByteArray());*/
result = BitmapFactory.decodeStream(is1);
//result = ImageUtils.decodeSuitableBitmap(is,60,60);
//result = ImageUtils.decodeSuitableBitmap(string,1,1);
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
//Log.i(TAG,“resutl size:”+result.getByteCount());
//result = ImageUtils.decodeSampledBitmapFromInputStream(is1,is2,1,1); Log.i(TAG,“resutl size:”+(result !=null?result.getByteCount():“null”));
/*if (result==null){
Log.i(TAG,“result==null”); }*/ //Log.i(TAG,“result=”+result); //优化图片加载 end
conn.disconnect();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(is1!=null){
is1.close();
}
/*if(is2!=null){
is2.close(); }*/ } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return result;
}
//滚动时的优化 begin
private static Set mSets ;
private ListView mListView;
public ListView getmListView() {
return mListView;
}
public void setmListView(ListView mListView) {
this.mListView = mListView;
}
public void loadImages(int mStart, int mEnd) {
Log.i(TAG, “loadImages:” + mStart+"-"+mEnd);
for (int i = mStart; i < mEnd; i++) {
Log.i(TAG, “loadImages:”+i);
String url = MainActivity.urls.get(i);
Bitmap bm = getBitmapFromCache(url);
ImageView mImageView = (ImageView)mListView.findViewWithTag(url);
if(null!=bm && null!= mImageView){
mImageView.setImageBitmap(bm);
}
else{//重新下载
NewsImageAsyncTask task = new NewsImageAsyncTask(url);
mSets.add(task);
task.execute();
}
}
}
public void cancelAllTasks() {
if(mSets!=null){
for (NewsImageAsyncTask task : mSets) {
task.cancel(false);
}
}
}
//看缓存中是否有 有则设置 没有则默认图片不管
public Bitmap setDefaultBitmap(ImageView pic, String newsPicResUrl) {
Bitmap bm = getBitmapFromCache(newsPicResUrl);
if(null!=bm){
pic.setImageBitmap(bm);
}
return bm;
}
//滚动时的优化 end
//硬盘缓存 加载图片方法(不返回bitmap,为了通用,不仅仅保存图片) 并写入硬缓存 begin private static boolean getBitmapUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
out = new BufferedOutputStream(outputStream, 8 * 1024);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
return false;
}
//硬盘缓存 加载图片方法 end
//硬盘缓存 下载图片 存入缓存(SD ,内存都存入)方法 begin
@Nullable
private Bitmap getBitmapAndSaveToCacheByUrl(String mUrl) {
String key = FileUtils.toMD5String(mUrl);
FileDescriptor fileDescriptor = null;
FileInputStream fileInputStream = null;
DiskLruCache.Snapshot snapShot = null;
try {
//尝试获取硬缓存里的数据
snapShot = mDiskCache.get(key);
//如果没有缓存
if (snapShot == null) {
//尝试读从网络取并写入
DiskLruCache.Editor editor = mDiskCache.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (getBitmapUrlToStream(mUrl, outputStream)) {
editor.commit();
} else {
editor.abort();
}
}
//再次读取
snapShot = mDiskCache.get(key);
}
if (snapShot != null) {
fileInputStream = (FileInputStream) snapShot.getInputStream(0);
fileDescriptor = fileInputStream.getFD();
}
//利用读取的硬盘数据,生成bitmap
Bitmap bitmap = null;
if (fileDescriptor != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
}
//利用bitmap 存入内存缓存
if (bitmap != null) {
putBitmapToCache(mUrl, bitmap);
}
//返回bitmap
return bitmap;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileDescriptor == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
}
}
}
return null;
}
//end
//加载大图
public void loadBigBitmap(String url, ImageView imageView, ProgressBar mProgressBar){
if(imageView!=null && null!= url){
new BigImageAsyncTask(imageView,mProgressBar).execute(url);
}
}
private class BigImageAsyncTask extends AsyncTask<String,Void,Bitmap> {
private ImageView mImageView;
private ProgressBar mProgressBar;
public BigImageAsyncTask(ImageView imageView, ProgressBar progressBar) {
mImageView = imageView;
mProgressBar = progressBar;
}
@Override
protected Bitmap doInBackground(String… params) {
return getBitmapByUrl(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap!=null)
mImageView.setImageBitmap(bitmap);
if(null!=mProgressBar){
mProgressBar.setVisibility(View.GONE);
}
}
}
}
package com.example.asynctaskdemo;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ProgressBar;
/**
* Created by zhangxutong on 2015/12/25. */
public class BigImageActivity extends Activity{
private ImageView mBigImageView;
private ProgressBar mProgressBar;
private ImageLoader mImageLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bigimage);
initView();
mImageLoader = ImageLoader.getInstance(BigImageActivity.this);
Intent intent = getIntent() ;
String urlBig = intent.getStringExtra(“urlBig”);
String urlSmall = intent.getStringExtra(“urlSmall”);
//设置初始值
if(null!=urlSmall) {
Bitmap bitmap = mImageLoader.getBitmapFromCache(urlSmall);
Log.i(“TAG”,“urlSmall:”+urlSmall+", bitmap:"+bitmap);
if(null!=bitmap){
mBigImageView.setImageBitmap(bitmap);
}
}