【声明】

欢迎转载,但请保留文章原始出处→_→

生命壹号:http://www.cnblogs.com/smyhvae/

文章来源:http://www.cnblogs.com/smyhvae/p/4488049.html

联系方式:smyhvae@163.com

效果图:(gif图太大了,有点卡,建议将图片保存到本地查看或者直接本文末尾的源码查看gif图)

加载网络图片我们用universal-image-loader,然后实现ListView的上拉下拉刷新我们用PullToRefresh。下面开始写代码。

整个代码的工程文件结构如下:

  • libs文件夹下是需要用到的一些库和开源框架(这里有个picasso框架,是用来加载网络图片的,暂时不用哈,留着以后备用,现在这个项目用的是universal-image-loader)。
  • adapter文件夹下是listView的自定义适配器(本文的重点)
  • entities是从网络获取到json数据,解析之后,用来存放这些数据的实体
  • utils文件夹下是url的常量
  • MainActivity.java是主程序的入口
  • MyApplication才是真正的app的第一个入口,这个不多解释,都懂得。

一、开始写代码:

(1)activity_main.xml(MainActvity的布局)

 <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"> <com.handmark.pulltorefresh.library.PullToRefreshListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"> </com.handmark.pulltorefresh.library.PullToRefreshListView>
</RelativeLayout>

这里就放了个PullToRefreshListView,其实本质上还是个ListView

(2)item_listview.xml(ListView中单个item的布局)

 <LinearLayout 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"
android:orientation="vertical"
> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="28dp"> <!--作者头像-->
<ImageButton
android:id="@+id/mVideoAvatarBtn"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@mipmap/defaultimg"/> <!--昵称-->
<TextView
android:id="@+id/mVideoNicknameTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
android:layout_toRightOf="@+id/mVideoAvatarIv"
android:singleLine="true"
android:text="张三"
android:textSize="16sp"/> </LinearLayout> <!--视频缩略图-->
<ImageButton
android:id="@+id/mVideoImgBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> </LinearLayout>

单个item中,一个是头像,一个是文本,一个是图片(包裹内容),其布局效果如下:

(3)MyApplication.java:

 package com.smyhvae.pulltorefreshdemo;

 import android.app.Application;

 import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; /**
* Created by smyhvae on 2015/5/8.
*/
public class MyApplication extends Application { @Override
public void onCreate() {
super.onCreate(); //创建默认的ImageLoader配置参数
ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this)
.writeDebugLogs() //打印log信息
.build(); //Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(configuration);
} }

主程序一进来,我们就在onCreate()中创建ImageLoader的配置参数,并初始化到ImageLoader中。

(4)JavaBean的实体:

这个其实就是下面的这些实体:

这个不需要赘述,代码略,在本文最后有源码下载链接。

(5)ViewHolder.java:(ListView的万能模板,嘿嘿)

 package com.smyhvae.pulltorefreshdemo.adapter;

 import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; /**
* Created by smyhvae on 2015/5/4.
* 通用的viewHolder类
*/
public class ViewHolder { private SparseArray<View> mViews;
private int mPosition;
private View mConvertView; public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mPosition = position;
this.mViews = new SparseArray<View>(); mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); mConvertView.setTag(this); } public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(context, parent, layoutId, position);
} else {
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.mPosition = position; //即时ViewHolder是复用的,但是position记得更新一下
return holder;
}
} /*
通过viewId获取控件
*/
//使用的是泛型T,返回的是View的子类
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId); if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
} return (T) view;
} public View getConvertView() {
return mConvertView;
} }

(6)ListViewAdapter.java:(同样是ListView的万能模板)

 package com.smyhvae.pulltorefreshdemo.adapter;

 import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter; import java.util.List; /**
* Created by smyhvae on 2015/5/4.
* 通用的ListView的BaseAdapter,所有的ListView的自定义adapter都可以继承这个类哦
*/
public abstract class ListViewAdapter<T> extends BaseAdapter { //为了让子类访问,于是将属性设置为protected
protected Context mContext;
protected List<T> mDatas;
protected LayoutInflater mInflater;
private int layoutId; //不同的ListView的item布局肯能不同,所以要把布局单独提取出来 public ListViewAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
this.mDatas = datas;
this.layoutId = layoutId;
} @Override
public int getCount() {
return mDatas.size();
} @Override
public T getItem(int position) {
return mDatas.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
//初始化ViewHolder,使用通用的ViewHolder,一样代码就搞定ViewHolder的初始化咯
ViewHolder holder = ViewHolder.get(mContext, convertView, parent, layoutId, position);//layoutId就是单个item的布局 convert(holder, getItem(position));
return holder.getConvertView(); //这一行的代码要注意了
} //将convert方法公布出去
public abstract void convert(ViewHolder holder, T t); }

(7)【非常非常重要】VideoListViewAdapter.java:

这个才是我们的这个ListView的自定义适配器哦:

 package com.smyhvae.pulltorefreshdemo.adapter;

 import android.content.Context;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.smyhvae.pulltorefreshdemo.R;
import com.smyhvae.pulltorefreshdemo.entities.Video;
import com.smyhvae.pulltorefreshdemo.utils.Constants; import java.util.List; /**
* Created by smyhvae on 2015/5/5.
*/ public class VideoListViewAdapter extends ListViewAdapter<Video> { DisplayImageOptions options; // DisplayImageOptions是用于设置图片显示的类 //MyAdapter需要一个Context,通过Context获得Layout.inflater,然后通过inflater加载item的布局
public VideoListViewAdapter(Context context, List<Video> datas) {
super(context, datas, R.layout.item_listview);
} /* @Override
public void convert(ViewHolder holder, Bean bean) { ((TextView) holder.getView(R.id.titleTv)).setText(bean.getTitle());
((TextView) holder.getView(R.id.descTv)).setText(bean.getDesc());
((TextView) holder.getView(R.id.timeTv)).setText(bean.getTime());
((TextView) holder.getView(R.id.phoneTv)).setText(bean.getPhone()); *//*
TextView tv = holder.getView(R.id.titleTv);
tv.setText(...); ImageView view = getView(viewId);
Imageloader.getInstance().loadImag(view.url);
/*//*
}*/ @Override
public void convert(ViewHolder holder, final Video video) { //1、作者的头像
ImageButton mVideoAvatarBtn = holder.getView(R.id.mVideoAvatarBtn);
//如果用的是开源框架Picasso获取网络图片,那就按照下面注释掉这一行代码来做。
// load方法里的参数是请求的图片的url。placeholder方法中的参数是说,加载图片成功之前默认显示的图片
//Picasso.with(mContext).load(Constants.CONTENT_HOST + video.getUserAvatarUrl()).placeholder(R.mipmap.ic_launcher).into(mVideoAvatarBtn);
String imageUrl = Constants.CONTENT_HOST + video.getUserAvatarUrl(); /*
下面的加载网络图片中,用到了Android-Universal-Image-Loader框架
*/
//显示图片的配置
// 使用DisplayImageOptions.Builder()创建DisplayImageOptions
options = new DisplayImageOptions.Builder()
.showStubImage(R.mipmap.phone) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.default_ptr_flip) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED) //图片会缩放到目标大小完全。非常重要,也就是说,这个view有多大,图片就会缩放到多大
.build(); ImageLoader.getInstance().displayImage(imageUrl, mVideoAvatarBtn, options); //2、作者的昵称
TextView mVideoNicknameTv = holder.getView(R.id.mVideoNicknameTv);
mVideoNicknameTv.setText(video.getUserNickName()); //3、视频的缩略图
ImageButton mVideoImgBtn = holder.getView(R.id.mVideoImgBtn); //让缩略图的宽度为手机屏幕的宽度,高度为手机屏幕宽度的一半。说白了,就是让 图片的尺寸为2:1
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
(int) (Constants.displayWidth * 0.5f + 0.5f));
mVideoImgBtn.setLayoutParams(params); String PicUrl = Constants.CONTENT_HOST + video.getPicUrl(); //Picasso.with(mContext).load(Constants.CONTENT_HOST + video.getPicUrl()).placeholder(R.mipmap.defaultimg).into(mVideoImgBtn);
ImageLoader.getInstance().displayImage(PicUrl, mVideoImgBtn, options); System.out.println("---->" + video.getPicUrl()); //跳转到具体是哪一个视频(即item的详情页)
/* mVideoImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int id = video.getVideoUrl();
mContext.startActivity(new Intent());
}
});*/
}
}

尤其要注意第75行的属性哦,这样可以让图片缩放到当前控件的大小。(如果没有这一行,图片大小就是包裹内容;如果加了这一行,图片大小就是匹配当前控件的大小,因为我在第88行设置了这个ImageButton的宽度是手机屏幕的宽度,高度是手机屏幕宽度的一半,这样的话,不管网络上的 图片是多大,都能够保证显示出来的图片比例是2:1)

(8)MainActivity.java:

 package com.smyhvae.pulltorefreshdemo;

 import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast; import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;
import com.smyhvae.pulltorefreshdemo.adapter.VideoListViewAdapter;
import com.smyhvae.pulltorefreshdemo.entities.ResponseObject;
import com.smyhvae.pulltorefreshdemo.entities.Video;
import com.smyhvae.pulltorefreshdemo.entities.VideoResponse;
import com.smyhvae.pulltorefreshdemo.utils.Constants; import java.util.List; public class MainActivity extends Activity { private PullToRefreshListView lv;
private Context mContext; private List<Video> videoList; //用来存放视频列表的集合 private int page = 0; //当前页码
private int size = 10; //每页显示10个
private int count = 0; //当前页面有多少个视频 private VideoListViewAdapter videoListViewAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//第一个Activity加载进来时,我们就获取屏幕的宽度和高度
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
Constants.displayWidth = displayMetrics.widthPixels;
Constants.displayHeight = displayMetrics.heightPixels; initView(); } private void initView() {
lv = (PullToRefreshListView) findViewById(R.id.lv); /*
设置刷新的模式:
可选值为:disabled(禁用下拉刷新),
pullFromStart(仅支持下拉刷新),
pullFromEnd(仅支持上拉刷新),
both(二者都支持),
manualOnly(只允许手动触发)
*/
lv.setMode(PullToRefreshBase.Mode.BOTH); //让这个Listview支持上拉加载更多,下拉刷新
lv.setScrollingWhileRefreshingEnabled(true);//滚动的时候不允许刷新,要不然么会很乱
//很重要,刷新时做回调
lv.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {
@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
//在这里做数据加载的操作
loadData(refreshView.getScrollY() < 0);
}
}); //首次打开页面时,延时200ms后自动加载数据
new Handler (new Handler.Callback(){
@Override
public boolean handleMessage(Message msg) {
lv.setRefreshing();
return true;
}
}).sendEmptyMessageDelayed(0,200);
} //如果是true表示下拉刷新,false表示上拉加载更多(如果y值小于0,说明是下拉操作)
private void loadData(final boolean direction) {
//http://172.24.1.49:8081/video/getVideos?apikey= &typeid=1&page=1
RequestParams params = new RequestParams(); if (direction) { //如果是上拉,那应该将page变为第一页
page = 1; } else {
page++; //如果是下拉,就让page加1 } params.addQueryStringParameter("page", String.valueOf(page)); //默认显示第一页
// params.addQueryStringParameter("size", "10"); //每页显示10个 new HttpUtils().send(HttpRequest.HttpMethod.GET, Constants.VIDEO_LIST + "typeid=1&", params, new RequestCallBack<String>() {
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
lv.onRefreshComplete();
Log.d("json", "---video的json数据>" + responseInfo.result); //解析服务器端的json数据
Gson gson = new GsonBuilder().create();
ResponseObject<VideoResponse> object = gson.fromJson(responseInfo.result, new TypeToken<ResponseObject<VideoResponse>>() {
}.getType());
/* ResponseObject<VideoResponse> object = new GsonBuilder().create().fromJson(responseInfo.result, new TypeToken<VideoResponse>() {
}.getType());*/
page = Integer.parseInt(object.getResult().getPage()); //获取服务器端返回来的当前页码
count = object.getResult().getCnt(); //获取当前页面有多少个视频
Log.d("json","---当前页面的item的个数>"+count);
if (direction) { //下拉刷新
videoList = object.getResult().getVideos(); //获取视频信息的集合,并存放 videoListViewAdapter = new VideoListViewAdapter(MainActivity.this,videoList);
lv.setAdapter(videoListViewAdapter); //为这个listView绑定适配器 } else {//尾部加载更多
videoList.addAll(object.getResult().getVideos()); } if (count == 0) { //如果当前页面已经没有视频了,那就告诉客户端,不要再拉了,因为后面没有数据了。
lv.setMode(PullToRefreshBase.Mode.PULL_FROM_START);
} } @Override
public void onFailure(HttpException e, String s) {
lv.onRefreshComplete();//不管是请求成功还是请求失败,我们都停止加载数据
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show(); }
}); } } 

这个MainActivity中讲到了xUtils怎样获取到网络上的json数据,并用Gson解析,然后用pull to refresh处理上拉下拉刷新的逻辑,好吧,确实是快速开发,用到的框架还挺多的好伐~

【工程文件】

2015-05-08-PullToRefreshDemo.rar

Android代码优化----PullToRefresh+universal-image-loader实现从网络获取数据并刷新的更多相关文章

  1. Android开源库--Universal Image Loader通用图片加载器

    如果说我比别人看得更远些,那是因为我站在了巨人的肩上.   github地址:https://github.com/nostra13/Android-Universal-Image-Loader 介绍 ...

  2. Android网络之数据解析----使用Google Gson解析Json数据

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  3. Android Volley 库通过网络获取 JSON 数据

    本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库通过网络获取 JSON 数据 参考资料 Android 关于网络操作一般都会介绍 HttpC ...

  4. Android中Universal Image Loader开源框架的简单使用

    UIL (Universal Image Loader)aims to provide a powerful, flexible and highly customizable instrument ...

  5. 【Android应用开发】 Universal Image Loader ( 使用简介 | 示例代码解析 )

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/50824912 相关地址介绍 : -- Universal I ...

  6. android universal image loader 缓冲原理详解

    1. 功能介绍 1.1 Android Universal Image Loader Android Universal Image Loader 是一个强大的.可高度定制的图片缓存,本文简称为UIL ...

  7. 开源项目Universal Image Loader for Android 说明文档 (1) 简介

     When developing applications for Android, one often facesthe problem of displaying some graphical ...

  8. 开源项目Universal Image Loader for Android 说明文档 (1) 简单介绍

     When developing applications for Android, one often facesthe problem of displaying some graphical ...

  9. universal image loader在listview/gridview中滚动时重复加载图片的问题及解决方法

    在listview/gridview中使用UIL来display每个item的图片,当图片数量较多需要滑动滚动时会出现卡顿,而且加载过的图片再次上翻后依然会重复加载(显示设置好的加载中图片) 最近在使 ...

随机推荐

  1. 性能分析之-- JAVA Thread Dump 分析综述

    性能分析之-- JAVA Thread Dump 分析综述       一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...

  2. 前端技巧:禁止浏览器static files缓存篇(转)

    前端技巧:禁止浏览器static files缓存篇 由于CSS/JS文件经常需要改动,前端调试时是不希望浏览器缓存这些文件的. 本文记录博主的经验. Meta法 目前在chrome调试还没有遇到问题, ...

  3. ASP.NET MVC中将控制器分离到类库的实现

    前言 在ASP.NET MVC的开发中,我们创建完项目之后,ASP.NET MVC是已Model-Controller-View的形式存在的,在创建项目自动生成的内容上Model我们很容易分离成类库, ...

  4. SQL Server join介绍

    介绍Inner Join(可以省略Inner,平常经常inner,就是inner join), Full Out Join,Cross Join,Left Join, Right Join区别. )) ...

  5. ABAP modify screen:修改屏幕,实现隐藏、禁止输入字段

    Loop at screen会loop处理屏幕上的每一个组件,并对其做相应的处理. SELECTION-SCREEN: BEGIN OF BLOCK B1 WITH FRAME.PARAMETERS  ...

  6. Atitit. Xss 漏洞的原理and应用xss木马

    Atitit. Xss 漏洞的原理and应用xss木马 1. XSS漏洞1 2. XSS的用途2 2.1. 盗取cookie2 2.2. 刷新流量 刷分3 2.3. DOS 窃取隐私”.“假冒身份”. ...

  7. 转发离线安装 Android Studio 更新

    1.在线更新 随着 Android Studio 的越来越完善与流行,无论从功能性,还是性能上,它正在成为广大 Android 开发者的首选.但是因为总所周知墙的原因,我们在 Android Stud ...

  8. Fresco 使用笔记(一):加载gif图片并播放

    项目总结 --------------------------------------------------------------------- 前言: 项目中图文混合使用的太多太多了,但是绝大部 ...

  9. Effective Java 阅读笔记——并发

    66:同步访问共享的可变数据 synchronized:1互斥,阻止线程看到的对象处于不一致的状态:2保证线程在进入同步区时能看到变量的被各个线程的所有修改 Java中,除了long或者double, ...

  10. iOS网络检测Reachability 使用 Demo,可检测2、3、4G

    你可以在Github下载这个Demo https://github.com/JanzTam/Reachability_Demo 首先,引入系统的Reachability类,不知道怎么引入的话,在Xco ...