没有看过上一篇文章的话,建议先去阅读GooglePlay:9.代码抽取(adapter)
项目框架的搭建:

以后每个view都是holder

BaseHolder

  1. public abstract class BaseHolder<Data>  {//写data和t一样
    private View contentView;
    private Data data;
    protected BitmapUtils bitmapUtils;
    public BaseHolder(){
    bitmapUtils = BitmapHelper.getBitmapUtils();
    contentView=initView();
    contentView.setTag(this);
    }
    /** 创建界面*/
    public abstract View initView();
    public View getContentView() {
    return contentView;
    }
    public void setData(Data data){
    this.data=data;
    refreshView(data);
    }
    /** 根据数据刷新界面*/
    public abstract void refreshView(Data data);
    }
MoreHolder 
  1. public class MoreHolder extends BaseHolder<Integer> {
    public static final int HAS_NO_MORE=0; // 没有额外数据了
    public static final int LOAD_ERROR=1;// 加载失败
    public static final int HAS_MORE=2;// 有额外数据 private RelativeLayout rl_more_loading,rl_more_error; /**当Holder显示的时候 显示什么样子*/
    @Override
    public View initView() {
    View view=UiUtils.inflate(R.layout.load_more);
    rl_more_loading=(RelativeLayout) view.findViewById(R.id.rl_more_loading);
    rl_more_error=(RelativeLayout) view.findViewById(R.id.rl_more_error);
    return view;
    }
    private DefaultAdapter adapter; public MoreHolder(DefaultAdapter adapter) {
    super();
    this.adapter=adapter; }
    @Override
    public View getContentView() {
    loadMore(); return super.getContentView();
    }
    private void loadMore() {
    // 请求服务器 加载下一批数据
    // 交给Adapter 让Adapter 加载更多数据
    adapter.loadMore();
    }
    /**根据数据做界面的修改*/
    @Override
    public void refreshView(Integer data) {
    rl_more_error.setVisibility(data==LOAD_ERROR?View.VISIBLE:View.GONE);
    rl_more_loading.setVisibility(data==HAS_MORE?View.VISIBLE:View.GONE); }
    }
DefaultAdapter : 多种不同类型条目的ListView 
  1. public abstract class DefaultAdapter<Data> extends BaseAdapter {
    protected List<Data> datas;
    private static final int DEFAULT_ITEM = 0;
    private static final int MORE_ITEM = 1;
    public List<Data> getDatas() {
    return datas;
    }
    public void setDatas(List<Data> datas) {
    this.datas = datas;
    }
    public DefaultAdapter(List<Data> datas) {
    this.datas = datas;
    }
    @Override
    public int getCount() {
    return datas.size() + 1; // 最后的一个条目 就是加载更多的条目
    }
    @Override
    public Object getItem(int position) {
    return datas.get(position);
    }
    /** 根据位置 判断当前条目是什么类型 */
    @Override
    public int getItemViewType(int position) { //20
    if (position == datas.size()) { // 当前是最后一个条目
    return MORE_ITEM;
    }
    return getInnerItemViewType(position); // 如果不是最后一个条目 返回默认类型
    }
    private int getInnerItemViewType(int position) {
    return DEFAULT_ITEM;
    }
    /** 当前ListView 有几种不同的条目类型 */
    @Override
    public int getViewTypeCount() {
    return super.getViewTypeCount() + 1; // 2 有两种不同的类型
    }
    @Override
    public long getItemId(int position) {
    return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
    BaseHolder holder = null;
    switch (getItemViewType(position)) { // 判断当前条目时什么类型
    case MORE_ITEM:
    if(convertView==null){
    holder=getMoreHolder();
    }else{
    holder=(BaseHolder) convertView.getTag();
    }
    break;
    case DEFAULT_ITEM:
    if (convertView == null) {
    holder = getHolder();
    } else {
    holder = (BaseHolder) convertView.getTag();
    }
    if (position < datas.size()) {
    holder.setData(datas.get(position));
    }
    break;
    }
    return holder.getContentView(); // 如果当前Holder 恰好是MoreHolder 证明MoreHOlder已经显示
    }
    private MoreHolder holder;
    private BaseHolder getMoreHolder() {
    if(holder!=null){
    return holder;
    }else{
    holder=new MoreHolder(this);
    return holder;
    }
    }
    protected abstract BaseHolder<Data> getHolder(); /**
    * 当加载更多条目显示的时候 调用该方法
    */
    public void loadMore() {
    ThreadManager.getInstance().createLongPool().execute(new Runnable() { @Override
    public void run() {
    // 在子线程中加载更多
    final List<Data> newData = onload();
    UiUtils.runOnUiThread(new Runnable() { @Override
    public void run() {
    if(newData==null){
    holder.setData(MoreHolder.LOAD_ERROR);//
    }else if(newData.size()==0){
    holder.setData(MoreHolder.HAS_NO_MORE);
    }else{
    // 成功了
    holder.setData(MoreHolder.HAS_MORE);
    datas.addAll(newData);// 给listView之前的集合添加一个新的集合
    notifyDataSetChanged();// 刷新界面 } }
    }); }
    });
    }
    /**
    * 加载更多数据
    */
    protected abstract List<Data> onload();
    }
 
修改8的代码SubjectFragment
  1. public class SubjectFragment extends BaseFragment {
    private List<SubjectInfo> datas;
    @Override
    public View createSuccessView() {
    BaseListView listView=new BaseListView (UiUtils.getContext());
    listView.setAdapter(new SubjectAdapter(datas));
    return listView;
    }
    private class SubjectAdapter extends DefaultAdapter<SubjectInfo>{
    public SubjectAdapter(List<SubjectInfo> datas) {
    super(datas);
    }
    @Override
    protected BaseHolder<SubjectInfo> getHolder() {
    return new SubjectHolder();
    }
    @Override
    protected List<SubjectInfo> onload() {
    SubjectProtocol protocol=new SubjectProtocol();
    List<SubjectInfo> load = protocol.load(0);
    datas.addAll(load);
    return load;
    }
    }
    class SubjectHolder extends BaseHolder<SubjectInfo>{
    ImageView item_icon;
    TextView item_txt;
    @Override
    public View initView() {
    View contentView=UiUtils.inflate(R.layout.item_subject);
    this.item_icon=(ImageView) contentView.findViewById(R.id.item_icon);
    this.item_txt=(TextView) contentView.findViewById(R.id.item_txt);
    return contentView;
    }
    @Override
    public void refreshView(SubjectInfo data) {
    this.item_txt.setText(data.getDes());
    bitmapUtils.display(this.item_icon, HttpHelper.URL+"image?name="+data.getUrl());
    }
    }
    @Override
    protected LoadResult load() {
    SubjectProtocol protocol=new SubjectProtocol();
    datas = protocol.load(0);
    return checkData(datas);
    }
    }
都是首页、APP、游戏页面很相似,所有又可以抽取
ListBaseHolder 
public class ListBaseHolder extends BaseHolder<AppInfo> {
ImageView item_icon;
TextView item_title,item_size,item_bottom;
RatingBar item_rating; public void refreshView(AppInfo data){
this.item_title.setText(data.getName());// 设置应用程序的名字
String size=Formatter.formatFileSize(UiUtils.getContext(), data.getSize());
this.item_size.setText(size);
this.item_bottom.setText(data.getDes());
float stars = data.getStars();
this.item_rating.setRating(stars); // 设置ratingBar的值
String iconUrl = data.getIconUrl(); //http://127.0.0.1:8090/image?name=app/com.youyuan.yyhl/icon.jpg // 显示图片的控件
bitmapUtils.display(this.item_icon, HttpHelper.URL+"image?name="+iconUrl);
}
@Override
public View initView() {
View contentView=View.inflate(UiUtils.getContext(), R.layout.item_app, null);
this.item_icon=(ImageView) contentView.findViewById(R.id.item_icon);
this.item_title=(TextView) contentView.findViewById(R.id.item_title);
this.item_size=(TextView) contentView.findViewById(R.id.item_size);
this.item_bottom=(TextView) contentView.findViewById(R.id.item_bottom);
this.item_rating=(RatingBar) contentView.findViewById(R.id.item_rating);
return contentView;
}
}
ListBaseAdapter 
  1. public abstract class ListBaseAdapter extends DefaultAdapter<AppInfo> {
    public ListBaseAdapter(List<AppInfo> datas) {
    super(datas);
    }
    @Override
    protected BaseHolder<AppInfo> getHolder() {
    return new ListBaseHolder();
    }
    @Override
    protected abstract List<AppInfo> onload(); }
GameFragment 
public class GameFragment extends BaseFragment {
private List<AppInfo> datas;
/**
* 加载成功的界面
*/
@Override
public View createSuccessView() {
BaseListView listView=new BaseListView(UiUtils.getContext());
listView.setAdapter(new ListBaseAdapter(datas){
@Override
protected List<AppInfo> onload() {
GameProtocol protocol=new GameProtocol();
List<AppInfo> load = protocol.load(datas.size()); //
datas.addAll(load);
return load;
} });
return listView;
}
/**
* 请求服务器加载数据
*/
@Override
protected LoadResult load() {
GameProtocol protocol=new GameProtocol();
datas = protocol.load(0);
return checkData(datas);
}
}
AppFragment 
public class AppFragment extends BaseFragment {
private List<AppInfo> datas;
/**
* 当加载成功的时候 显示的界面
*/
@Override
public View createSuccessView() {
BaseListView listView=new BaseListView(UiUtils.getContext());
listView.setAdapter(new ListBaseAdapter(datas){
@Override
protected List<AppInfo> onload() {
AppProtocol protocol=new AppProtocol();
List<AppInfo> load = protocol.load(0);
datas.addAll(load);
return load;
} });
return listView;
}
/**
* 请求服务器 获取服务器的数据
*/
protected LoadResult load() {
AppProtocol protocol=new AppProtocol();
datas = protocol.load(0);
return checkData(datas); // 检查数据 有三种结果 成功, 错误,空
}
}

  

首页有个几张图片的展示栏,所以又是一个holder
HomePictureHolder (自动轮询)
public class HomePictureHolder extends BaseHolder<List<String>> {
/* 当new HomePictureHolder()就会调用该方法 */
private ViewPager viewPager;
private List<String> datas;
@Override
public View initView() {
viewPager = new ViewPager(UiUtils.getContext());
viewPager.setLayoutParams(new AbsListView.LayoutParams(
LayoutParams.MATCH_PARENT, UiUtils
.getDimens(R.dimen.home_picture_height)));//转换成dp
return viewPager;
}
/* 当 holder.setData 才会调用 */
@Override
public void refreshView(List<String> datas) {
this.datas = datas;
viewPager.setAdapter(new HomeAdapter());
viewPager.setCurrentItem(2000*datas.size());// 设置起始的位置 Integer.Max_Vlue/2,这样开始位置也能向后划了
viewPager.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
runTask.stop();
break;
// 事件的取消,有可能按下viewpager滑动到listview上停止就不轮播了
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
runTask.start();
break;
} return false; // viewPager 触摸事件 返回值要是false
}
});
runTask = new AuToRunTask();
runTask.start();
}
boolean flag;
private AuToRunTask runTask;
//Runnable并不是开启子线程,所以可以在主线程运行,thread才是开启线程
public class AuToRunTask implements Runnable{
@Override
public void run() {
if(flag){
UiUtils.cancel(this); // 取消之前
int currentItem = viewPager.getCurrentItem();
currentItem++;
viewPager.setCurrentItem(currentItem);
// 延迟执行当前的任务
UiUtils.postDelayed(this, 2000);// 递归调用
}
}
public void start(){
if(!flag){
UiUtils.cancel(this); // 取消之前
flag=true;
UiUtils.postDelayed(this, 2000);// 递归调用
}
}
public void stop(){
if(flag){
flag=false;
UiUtils.cancel(this);
}
} } class HomeAdapter extends PagerAdapter {
// 当前viewPager里面有多少个条目
LinkedList<ImageView> convertView=new LinkedList<ImageView>();
// ArrayList
@Override
public int getCount() {
return Integer.MAX_VALUE;//这样写条目就能一直划了
}
/* 判断返回的对象和 加载view对象的关系 */
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
ImageView view=(ImageView) object;
convertView.add(view);// 把移除的对象 添加到缓存集合中
container.removeView(view);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int index=position%datas.size();//访问网络需要这个参数
ImageView view;
if(convertView.size()>0){
view=convertView.remove(0);
}else{
view= new ImageView(UiUtils.getContext());
}
bitmapUtils.display(view, HttpHelper.URL + "image?name="
+ datas.get(index));
container.addView(view); // 加载的view对象
return view; // 返回的对象
}
}
}
 
UiUtils 添加这三个方法 
  1.   /**
    * 延迟执行 任务
    * @param run 任务
    * @param time 延迟的时间
    */
    public static void postDelayed(Runnable run, int time) {
    BaseApplication.getHandler().postDelayed(run, time); // 调用Runable里面的run方法
    }
    /**
    * 取消任务
    * @param auToRunTask
    */
    public static void cancel(Runnable auToRunTask) {
    BaseApplication.getHandler().removeCallbacks(auToRunTask);
    } }
    这样写获取到图片高的dp
    <dimen name="home_picture_height">134dp</dimen>
    public static int getDimens(int homePictureHeight) {
    return (int) getResource().getDimension(homePictureHeight);
    }
 
HomeFragment 
public class HomeFragment extends BaseFragment {
private List<AppInfo> datas;
private List<String> pictures; // 顶部ViewPager 显示界面的数据 // 当Fragment挂载的activity创建的时候调用
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
show();
}
public View createSuccessView() {
BaseListView listView=new BaseListView(UiUtils.getContext());
HomePictureHolder holder=new HomePictureHolder();
holder.setData(pictures);
View contentView = holder.getContentView(); // 得到holder里面管理的view对象
//contentView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
listView.addHeaderView(contentView); // 把holder里的view对象 添加到listView的上面 listView.setAdapter(new ListBaseAdapter(datas,listView){
@Override
protected List<AppInfo> onload() {
HomeProtocol protocol=new HomeProtocol();
List<AppInfo> load = protocol.load(datas.size());
datas.addAll(load);
return load;
}
@Override
public void onInnerItemClick(int position) {
super.onInnerItemClick(position);
Toast.makeText(getActivity(), "position:"+position, 0).show();
AppInfo appInfo = datas.get(position);
Intent intent=new Intent(UiUtils.getContext(), DetailActivity.class);
intent.putExtra("packageName", appInfo.getPackageName());//将包名传到详情页,详情页访问网络用包名
startActivity(intent);
} }); // 第二个参数 慢慢滑动的时候是否加载图片 false 加载 true 不加载
// 第三个参数 飞速滑动的时候是否加载图片 true 不加载
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true));
bitmapUtils.configDefaultLoadingImage(R.drawable.ic_default); // 设置如果图片加载中显示的图片
bitmapUtils.configDefaultLoadFailedImage(R.drawable.ic_default);// 加载失败显示的图片
return listView;
} public LoadResult load() {
HomeProtocol protocol=new HomeProtocol();
datas = protocol.load(0); // load index 从哪个位置开始获取数据 0 20 40 60
pictures = protocol.getPictures();
return checkData(datas);
}
}
 
修改DefaultAdapter,这样传调到详情页面的时候position
已经是修改过的了,我们并不希望去点首页的图片展示
  1. 	public DefaultAdapter(List<Data> datas,ListView lv) {
    this.datas = datas;
    // 给ListView设置条目的点击事件
    lv.setOnItemClickListener(this);
    this.lv=lv;
    } // ListView 条目点击事件回调的方法
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
    //Toast.makeText(UiUtils.getContext(), "position:"+position, 0).show();
    position=position-lv.getHeaderViewsCount();// 获取到顶部条目的数量 位置去掉顶部view的数量
    onInnerItemClick(position);
    }
    /**在该方法去处理条目的点击事件*/
    public void onInnerItemClick(int position) { }
 
面向holder编程
  1. 	public View createSuccessView() {
    BaseListView listView=new BaseListView(UiUtils.getContext());
    HomePictureHolder holder=new HomePictureHolder();
    holder.setData(pictures);
    View contentView = holder.getContentView(); // 得到holder里面管理的view对象
    contentView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
    listView.addHeaderView(contentView); // 把holder里的view对象 添加到listView的上面

10. 面向holder编程、自动轮询的更多相关文章

  1. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  2. c# 面向方面编程

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.Spring框架用的核心技术就是AOP,是函数式编程的一 ...

  3. 关于面向切面编程Aspect Oriented Programming(AOP)

    最近学到spring ,出来了一个新概念,面向切面编程,下面做个笔记,引自百度百科. Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题.AOP主要实 ...

  4. 30天C#基础巩固------面向鸭子编程,关于string和File的练习

         面向对象编程就是面向抽象的父类进行编程,具体的实现不用考虑,由子类决定.<经典的说法--面向鸭子编程> eg:鸭子的编程,<对于多态的理解>     我们都习惯把使用 ...

  5. Method Swizzling和AOP(面向切面编程)实践

    Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...

  6. iOS控制器瘦身-面向超类编程

    今天写这篇文章的目的,是提供一种思路,来帮助大家解决控制器非常臃肿的问题,对控制器瘦身. 滴滴 老司机要开车了 如果手边有项目,不妨打开工程看一下你的控制器代码有多少行,是不是非常多?再看一下tabl ...

  7. [转] AOP面向切面编程

    AOP面向切面编程 AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  8. Spring AOP: Spring之面向方面编程

    Spring AOP: Spring之面向方面编程 面向方面编程 (AOP) 提供从另一个角度来考虑程序结构以完善面向对象编程(OOP). 面向对象将应用程序分解成 各个层次的对象,而AOP将程序分解 ...

  9. 你听说过PHP 的面向方面编程吗?

    面向方面编程(AOP)对于PHP来说是一个新的概念.现在PHP对于 AOP 并没有官方支持,但有很多扩展和库实现了这个特性.本课中,我们将使用 Go! PHP library 来学习 PHP 如何进行 ...

随机推荐

  1. 编辑输出“Hello World”

    一.新建java项目 执行“文件->新建->项目建立”,打开建立新项目对话框,在编辑框中输入项目名,其他选项为默认值,随后点击“完成”按钮. 二.新建java类 执行“文件->新建- ...

  2. MySQL千万级数据库查询怎么提高查询效率

    在实际项目中,当MySQL表的数据达到百万级别时候,普通查询效率直线下降,而且当使用的where条件较多,其查询效率是让人无法容忍的.假如一个taobao订单查询详情要几十秒,可想而知的用户体验是多差 ...

  3. linux RCU机制

    参考资料: https://www.cnblogs.com/qcloud1001/p/7755331.html https://www.cnblogs.com/chaozhu/p/6265740.ht ...

  4. Jenkins自定义变量共享

    https://www.cnblogs.com/junneyang/p/5239480.html https://www.cnblogs.com/Rocky_/p/8317156.html https ...

  5. python 打包成 windows .EXE

    1. 升级pip python -m pip install --upgrade pip 2.安装 pyinstall (打包程序) pip install pyinstaller 3 开始打包(打包 ...

  6. windows任务栏IDEA图标变白色快速解决方法

    方案1:同时按Windows键+R键打开运行对话框,输入ie4uinit.exe -show然后回车即可修复. 方案2:打开计算机(Win7),此电脑(Win10)或任意文件夹,然后在地址栏输入cmd ...

  7. 密码与安全新技术专题之WEB应用安全

    学号 2018-2019-2 <密码与安全新技术专题>第1周作业 课程:<密码与安全新技术专题> 班级: 1892 姓名: 李熹桥 学号:20189214 上课教师:谢四江 上 ...

  8. IDEA集成git方法

    一.IDEA集成git方法 首先idea集成git我们需要先下载一个小软件,git bash  地址:https://git-scm.com/downloads  .下载好了之后直接下一步下一步傻瓜试 ...

  9. 【机器学习】支持向量机(SVM)的优化算法——序列最小优化算法(SMO)概述

    SMO算法是一一种启发式算法,它的基本思路是如果所有变量的解的条件都满足最优化问题的KKT条件,那么这个最优化问题的解就得到了.因为KKT条件是该优化问题的充分必要条件. 整个SMO算法包括两个部分: ...

  10. 一、PTA实验作业

    一.PTA实验作业 1.题目1: 6-2 线性表元素的区间删除 2. 设计思路 定义i,j; 判断L,minD,maxD; while(i<l->Last) { 判断所有满足条件的数,de ...