初学Android项目:开发电子市场<第二天>下

哟哟哟....

项目开发第二天,这里我完成了类似“电子市场”种应用的框架的整体搭建,已经完成了,以后的开发就按照这种方法去实现。

不断地抽取,将所有的公有部分抽取出来,这样编写的代码,就很简洁,清晰,明了。

感谢传智播客提供的教学视频,让我不断学习,不断完善自己。


下午,主要完成以下功能:

1.抽取MyBaseAdapter

2.写加载更多的Holder。MoreHolder

3.模拟加载更多地数据,测试。

运行效果图:


语言是苍白的,代码是真实的。

MyBaseAdapter.java

package com.example.adapter;

import java.util.List;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import com.example.holder.BaseHolder;
import com.example.holder.MoreHolder;
import com.example.manage.ThreadManager;
import com.example.utils.UIUtils;
/**
 * 将所有的adapter里面的holder和填充的数据抽取到MyBaseAdapter
 * @author bitaotao
 * @param <T> 需要填充的数据
 */
public abstract class MyBaseAdapter<T> extends BaseAdapter {
	private List<T> mDatas ;
	private BaseHolder<T> holder;
	public MyBaseAdapter(List<T> mDatas) {
		//在构造方法里面,就将数据设置进去
		setDatas(mDatas);
	}
	
	public List<T> getDatas() {
		return mDatas;
	}

	public void setDatas(List<T> mDatas) {
		this.mDatas = mDatas;
	}

	@Override
	public int getCount() {
		return mDatas.size() + 1;//加 1 是为了最后加载更多的布局
	}

	@Override
	public Object getItem(int position) {
		return mDatas.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}
	private final int MORE_VIEW_TYPE = 0; 
	private final int ITEM_VIEW_TYPE = 1;
	private MoreHolder moreHolder; 
	//根据position位置返回那种item展示类型
	@Override
	public int getItemViewType(int position) {
		if(position == getCount() - 1){
			return MORE_VIEW_TYPE;//加载更多地布局
		}else{
			return getItemViewTypeInner(position);
		}
	}

	private int getItemViewTypeInner(int position) {
		return ITEM_VIEW_TYPE;//普通的item的布局
	}
	//获取item有几种类型,默认是一种类型, 这里再加1是为了做加载更多
	@Override
	public int getViewTypeCount() {
		return super.getViewTypeCount() + 1;//加 1 是为了最后加载更多的布局
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if(null != convertView){
			holder = (BaseHolder<T>) convertView.getTag();
		}else{
			if(MORE_VIEW_TYPE == getItemViewType(position)){
				holder = getMoreHolder();
			}else{
				holder = getHolder();				
			}
			
			if(ITEM_VIEW_TYPE == getItemViewType(position)){
				holder.setData(getDatas().get(position));
			}
		}
		return holder.getRootView();
	}

	private BaseHolder getMoreHolder() {
		if(null == moreHolder){
			moreHolder = new MoreHolder(this,hasMore());			
		}
		return moreHolder;
	}
	/**
	 * 是否有更多数据
	 * @return
	 */
	public boolean hasMore() {
		return true;
	}

	public abstract BaseHolder<T> getHolder();
	private boolean is_loading = false;
	/**
	 * 加载更多数据
	 */
	public void loadMore() {
		//防止重复加载
		if(!is_loading){
			is_loading = true;
			ThreadManager.getLongPool().execute(new Runnable() {
				@Override
				public void run() {
					final List list = onLoadMore();
					UIUtils.runInMainThread(new Runnable() {
						
						@Override
						public void run() {
							if(null == list){
								getMoreHolder().setData(MoreHolder.ERROR);
							}else if(list.size() < 20){
								getMoreHolder().setData(MoreHolder.NO_MORE);
							}else{
								getMoreHolder().setData(MoreHolder.HAS_MORE);
							}
							
							if(null != list){
								if(null != mDatas){
									mDatas.addAll(list);
								}else{
									setDatas(list);
								}
							}
							notifyDataSetChanged();
							is_loading = false;
						}
					});
					
				}
			});
		}
		
	}

	public abstract List onLoadMore();

}

MoreHolder.java

package com.example.holder;

import com.example.R;
import com.example.adapter.MyBaseAdapter;
import com.example.utils.UIUtils;

import android.view.View;
import android.widget.RelativeLayout;

public class MoreHolder extends BaseHolder<Integer> {
	// 表示跟服务器交互成功,没有更多数据类型
	public static final int NO_MORE = 0;// 没有数据
	// 表示跟服务器交互成功,有更多数据类型
	public static final int HAS_MORE = 1;//有数据
	// 表示跟服器交互失败
	public static final int ERROR = 2;//错误
	private MyBaseAdapter adapter;
	private RelativeLayout rl_more_loading,rl_more_error;
	public MoreHolder(MyBaseAdapter adapter, boolean hasMore) {
		this.adapter = adapter;
		setData(hasMore ? HAS_MORE : NO_MORE);
	}
	
	@Override
	public View getRootView() {
		if(getData() == HAS_MORE){//有更多数据,调用加载更多方法
			loadMore();
		}
		return super.getRootView();
	}
	private void loadMore() {
		adapter.loadMore();
	}

	@Override
	public void refershView() {
		Integer data = getData();
		rl_more_loading.setVisibility(data == HAS_MORE ? View.VISIBLE : View.GONE);
		rl_more_error.setVisibility(data ==ERROR ? View.VISIBLE : View.GONE);
		
	}

	@Override
	public View initView() {
		View view = UIUtils.inflate(R.layout.list_more_loading);
		rl_more_loading = (RelativeLayout) view.findViewById(R.id.rl_more_loading);
		rl_more_error = (RelativeLayout) view.findViewById(R.id.rl_more_error);
		return view;
	}

}

HomeFragment.java

package com.example.fragment;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.widget.ListView;
import android.widget.TextView;

import com.btt.ui.widget.LoadingPager.LoadResult;
import com.example.adapter.MyBaseAdapter;
import com.example.holder.BaseHolder;
import com.example.utils.UIUtils;


public class HomeFragment extends BaseFragment {

	private List<String> mDatas;
	@Override
	protected View createSuccessView() {
		ListView mListView = new ListView(UIUtils.getContext());
		MyBaseAdapter adapter = new HomeAdapter(mDatas);
		mListView.setAdapter(adapter);
		return mListView;
	}

	@Override
	protected LoadResult load() {
		//模拟一些假数据
		mDatas = new ArrayList<String>();
		for (int i = 0; i < 30; i++) {
			mDatas.add("我是菜鸟"+i+"号");
		}
		return check(mDatas);
	}
	
	private class HomeAdapter<T> extends MyBaseAdapter{

		public HomeAdapter(List<T> mDatas) {
			super(mDatas);
		}

		@Override
		public BaseHolder getHolder() {
			return new ViewHolder();
		}

		@Override
		public List onLoadMore() {
			//模拟一些要加载的假数据
			List<String> moreData = new ArrayList<String>();
			for (int i = 0; i < 30; i++) {
				moreData.add("我是更多数据"+i);
			}
			return moreData;
		}

	}
	/**
	 * 这里我们新增了一个内部类ViewHolder,用于对控件的实例进行缓存。当convertView为空的时候,创建一个ViewHolder对象,
	 * 并将控件的实例存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View中。
	 * 当convertView不为空的时候则调用View的getTag()方法,把ViewHolder重新取出。这样所有控件的实例都缓存在了ViewHolder里
	 * @author bitaotao
	 */
	private class ViewHolder extends BaseHolder<String>{
		TextView tv;

		@Override
		public void refershView() {
			tv.setText(getData());//将获得的数据,设置给TextView
		}

		@Override
		public View initView() {
			tv  = new TextView(UIUtils.getContext());
			return tv;
		}
	}
}


学习总结:


上午没有总结,下午就总结在这里:

1.ListView的优化
在HomeFragment类新增一个内部类ViewHolder,用于对控件的实例进行缓存。
当convertView为空的时候,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法。
将ViewHolder的对象存储在View中。
当convertView不为空的时候则调用View的getTag()方法。把ViewHolder重新取出。这样所有控件的实例都缓存在了ViewHolder里,
就没有必要每次都通过findViewById()方法来获取控件实例了。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
//档convertView为空时
convertView = new TextView(UIUtils.getContext());//控件的实例,这里也可以加载布局,布局中就有控件
holder = new ViewHolder();//创建ViewHolder对象,用于缓存控件
holder.tv = (TextView) convertView;//将控件或者布局的实例都存放在ViewHolder里
convertView.setTag(holder);//将ViewHolder的对象存储在View中
}else{
//convertView不为空,把ViewHolder重新取出
holder = (ViewHolder) convertView.getTag();
}
//设置数据
holder.tv.setText(mDatas.get(position));
return convertView;
}

}
public class ViewHolder{
TextView tv;
}

2.抽取BaseHolder类,采用面向holder编程。
面向ListView编程时,在使用holder优化时,就相当于我们面向holder编程了。在使用ListView编写布局时,
需要填充数据,当我们抽取holder的时候,可以将布局和数据都抽取出来,因为每个ListView都有布局和填充的数据,
这些都是共性。
public abstract class BaseHolder<T> {
private View view;
private T data;
public BaseHolder(){
view = initView();//初始化view
view.setTag(this);//将holder对象存储在view中

}
...
}
3.抽取MyBaseAdapter类,将所有的adapter里面的holder和填充的数据抽取到MyBaseAdapter
public class MyBaseAdapter<T> extends BaseAdapter {
private List<T> mDatas;
private BaseHolder<T> holder;
public MyBaseAdapter(List<T> mDatas) {
//在构造方法里面,就将数据设置进去
setmDatas(mDatas);
}
...
}
4.写MoreHolder类,用于缓存加载更多的布局和数据
这里要显示加载更多地布局,就得覆写父类中的这两个方法:
@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
return super.getItemViewType(position);
}




@Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return super.getViewTypeCount();
}
具体详细实现请看MyBaseAdapter类和MoreHandler类


你可能感兴趣的:(ListView,传智播客,android项目,电子市场)