上篇是对ListView进行了封装处理,这一篇主要是记录在开发中学到的一些开发经验。
1.根据需求,ListView中的Item常常不止一种,如果要加载多种Item,只需要重写BaseAdapter中的getItemType()和getViewTypeCount()两个方法。
(1)getViewTypeCount()方法是得到Item种类的个数,就是,你想要加载几种布局,将种类个数告诉它。
(2)getItemType()方法,每一种Item都是一种类型,怎样加载,在ListView的什么position上加载哪种页面,都要在这个方法做判断。
@Override public int getItemViewType(int position) { if (position==getCount()-1){ return ITEM_MORE; }else { return getType(); } } public int getType(){ return ITEM_NORMAL; } @Override public int getViewTypeCount() { return 2; }
在这里有一个小技巧,对getType()这个方法的处理,为什么需要维护这个方法呢?
我们要知道,这里是在父类中对ListView的Adapter进行封装,子类的Item类型不确定,唯一确定的就是每一页的最底部的“加载中”的布局,如果子类的Item不是ITEM_NORMAL类型,我们可以直接在子类重写getType()方法,来随时修改Item的类型。
2.使一段代码每次只执行一次,(经常在家在网络数据时使用),先声明一个boolean型的变量,初始化为false,判断如果为false,那么将变量置为true,并执行代码,在执行完之后,再将变量置为false。
对于ITEM_MORE,它有三种状态,加载中,加载失败,无数据。加载中代表正在请求数据,请求到数据之后就会加载下一页数据,如果没有数据了,就会给用户提示,如果由于网络问题等原因导致加载失败,就会显示加载失败,请重试的布局。
怎样去判断是否有下一页呢,这要根据返回的数据来判断,我们设置了ListView一次性加载20条数据,如果返回的数据小于20的话,那么就代表已经没有了数据,也就没有下一页了。
那么怎样去得到返回的数据呢,在基类中是无法获知的,老办法,抽象方法onLoadData()交给子类去实现,将返回来的数据交给父类中的加载下一页的方法,让其进行判断,
public void loadMore(final MoreHolder moreHolder){ if (!isLoadMore){ isLoadMore=true; new Thread(new Runnable() { @Override public void run() { final ArrayList<T> moreData=onLoadData(); UIUtils.RunningMainThread(new Runnable() { @Override public void run() { if (moreData!=null){ //每一页有20 条数据,如果返回数据小于20条,就认为到了最后一页了,那么就没有更多数据了 if (moreData.size()<20){ moreHolder.setData(MoreHolder.STATE_LOAD_NONE); Toast.makeText(UIUtils.getContext(),"没有更多数据了",Toast.LENGTH_SHORT).show(); }else { moreHolder.setData(MoreHolder.STATE_LOAD_NONE); } data.addAll(moreData); MyBaseAdapter.this.notifyDataSetChanged(); }else { //加载更多失败 moreHolder.setData(MoreHolder.STATE_LOAD_ERROR); } isLoadMore=false; } }); } }).start(); }
根据返回数据的大小,去更改ITEM_MORE的布局,同时,如果获取到了数据,就将数据添加至原有的数据之中,在通知Adapter刷新界面(此时需要在主线程完成)
在继承了MyBaseAdapter的子类中去实现onLoadData(),子类实现这个方法主要是去获取网络的数据。
这部分逻辑很复杂,封装的劣势也就是在这里,需要好好体会,最好是打断点跟着代码走一遍,大致就会清楚了。个人还是倾向封装的,感觉用的很巧妙。