import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private final static String TAG = “zxt/MainActivity”;
private final String Url = “http://www.imooc.com/api/teacher?type=4&num=30”;
List mNewsDatas = null;
private RefreshListView mListView ;
private TextView mNoDatas;
//下拉数据刷新 改写数组为集合
//public static String[] urls; public static List urls;
//下拉数据刷新
private NewsAdapter mNewsAdapter;
//
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (RefreshListView) findViewById(R.id.listView1);
mNoDatas = (TextView) findViewById(R.id.tv_nodatas);
new NewTask().execute(Url);
}
//下拉刷新数据
/* public interface IRefreshCompleteListener{
public void onRefreshComplete(); } private IRefreshCompleteListener mRefreshComplete; public void IRefreshCompleteListener(IRefreshCompleteListener listener){ mRefreshComplete = listener; }*/ public void refreshData(RefreshListView listview){
//获取最新数据
setReflashData();
//֪ͨ������ʾ
//mRefreshComplete.onRefreshComplete();
}
//下拉刷新
private int newDataslength ;
private void setReflashData() {
new DownPullTask().execute(Url);
//执行更新 start
/*NewsBean bean = new NewsBean(); bean.NewsNo = “31”; bean.NewsName = “new Name”; bean.NewsDescription = “new Des”; bean.NewsPicResUrl = Math.random()>0.5? “https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png” : “https://img-my.youkuaiyun.com/uploads/201407/26/1406383291_6518.jpg”;*/
//执行更新 end
}
private void showList(List apk_list) {
//NewsAdapter adapter = (NewsAdapter) mListView.getAdapter();
/*if (adapter == null) { listview = (ReFlashListView) findViewById(R.id.listview); listview.setInterface(this); adapter = new MyAdapter(this, apk_list); listview.setAdapter(adapter); } else {*/ if(mNewsAdapter!=null)
mNewsAdapter.onDateChange(apk_list);
//}
}
private class DownPullTask extends AsyncTask<String,Void,List>{
@Override
protected List doInBackground(String… params) {
Log.i(TAG,“NewTask:doInBackground”);
return getDataByUrl(params[0]);
}
@Override
protected void onPostExecute(List newsBeens) {
super.onPostExecute(newsBeens);
//fix bug if first nodata
//更新了几条数据 if(null!=newsBeens){
newDataslength = newsBeens.size();
if(null==mNewsDatas ){
mNewsDatas = new ArrayList();
}
mNewsDatas.addAll(0,newsBeens);
showList(mNewsDatas);
//֪ͨlistview ˢ�������ϣ�
}else{
newDataslength = 0;
}
mNewsAdapter.refreshComplete(newDataslength);
setHintVisibility(newsBeens);
Log.i(TAG,“NewTask:onPostExecute:”+newDataslength);
Toast.makeText(MainActivity.this,“成功更新”+newDataslength+“条新闻”,Toast.LENGTH_SHORT).show();
}
}
//下拉刷新 end
class NewTask extends AsyncTask<String, Void, List> {
@Override
protected List doInBackground(String… params) {
return getDataByUrl(params[0]);
}
@Override
protected void onPostExecute(List result) {
super.onPostExecute(result);
//下拉刷新
mNewsAdapter= new NewsAdapter(MainActivity.this, result,mListView);
//下拉刷新
mListView.setAdapter(mNewsAdapter);
mListView.setOnScrollListener(mNewsAdapter);
// 处理下拉刷新
mListView.setOnTouchListener(mNewsAdapter);
mNewsDatas = result;
// 处理下拉刷新
//刷新回调 mNewsAdapter.setIRefereshListener(new IRefereshListener() {
@Override
public void onRefresh() {
mListView.postDelayed(new Runnable() {
@Override
public void run() {
refreshData(mListView);
}
}, 1000);
}
});
//刷新回调
setHintVisibility(result);
//加载更多begin
mNewsAdapter.setIOnScrollBottomListener(new NewsAdapter.IOnScrollBottomListener() {
@Override
public void onScrollBottom() {
mListView.postDelayed(new Runnable() {
@Override
public void run() {
//加载数据
loadMoreData();
mNewsAdapter.bottomDataLoadComplete();
}
}, 3000);
}
});
//加载更多end
}
}
//加载更多begin
private int index =100;
private void loadMoreData(){
NewsBean bean = new NewsBean();
bean.NewsNo = “”+index++;
bean.NewsPicResUrl = “https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png”;
/*List datas = mNewsAdapter.getDatas();
datas.add(-1,bean);*/ mNewsAdapter.setData(-1,bean);
mNewsAdapter.notifyDataSetChanged();
}
//加载更多end
private void setHintVisibility(List result) {
mNoDatas.setVisibility(result==null? View.VISIBLE:View.GONE);
}
public List getDataByUrl(String url) {
List datas = null;
try {
String jsonString = readStream(new URL(url).openStream());
datas = parseJson(jsonString);
//Log.i(“zxt”, “jsonString:”+jsonString);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return datas;
}
private List parseJson(String jsonString) {
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray(“data”);
JSONObject data = null;
List datas = new ArrayList();
NewsBean bean = null;
//处理下拉刷新加入
if(null==urls){
urls = new ArrayList();
}
List tempUrls = new ArrayList();
//处理下拉刷新加入
for (int i = 0; i < jsonArray.length(); i++) {
data = (JSONObject) jsonArray.get(i);
bean = new NewsBean();
bean.NewsPicResUrl = data.getString(“picSmall”);
//处理下拉刷新加入
tempUrls.add(bean.NewsPicResUrl);
//处理下拉刷新加入
bean.NewsName = data.getString(“name”);
bean.NewsDescription = data.getString(“description”);
bean.NewsNo = data.getString(“id”);
//加载大图加入
bean.NewsPicBigResUrl = data.getString(“picBig”);
//加载大图加入
datas.add(bean);
}
//处理下拉刷新加入 将新的url 加入到最上方
urls.addAll(0,tempUrls);
//处理下拉刷新加入
return datas;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private String readStream(InputStream is) {
StringBuilder jsonString = new StringBuilder();
try {
String line = “”;
InputStreamReader isr = new InputStreamReader(is, “utf-8”);
BufferedReader br = new BufferedReader(isr);
if (null != (line = br.readLine())) {
jsonString.append(line);
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonString.toString();
}
}
package com.example.asynctaskdemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class NewsAdapter extends BaseAdapter implements OnScrollListener,
OnTouchListener {
private static final String TAG = “zxt/NewsAdapter”;
private volatile List mDatas;
private LayoutInflater mInflater;
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;
i
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
mport 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 ;