自定义adapter的基础上Listview优化方案以及几个小错误(checkbox吃掉点击事件以及对象重复问题)

每次adapter运行都有一个getcount,有多少条就调用多少次getview,就会解析多少次xml文件(创建view,条数多了很消耗时间),13年谷歌提出了一个机制,每次只缓存一屏幕多几个,把划出屏幕外的listview回收(用的convertView),只要修改里面的值就可以重新用不用再创建一个view
修改的是自定义adapter中的getview方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Student student=mData.get(position);

if(convertView==null){
convertView=minflater.inflate(R.layout.simple_adpter,null);//没有就创建
}
//convertview代替了view,判断是否有划出屏幕的listviewconvertview),如果没有就新创建,有就不用创建直接赋值
ImageView imageview= (ImageView) convertView.findViewById(R.id.image_photo);
TextView textview_name= (TextView) convertView.findViewById(R.id.text_name);
TextView textview_sex= (TextView) convertView.findViewById(R.id.text_sex);
TextView textview_hobby= (TextView) convertView.findViewById(R.id.text_hobby);
textview_name.setText(student.getName());
textview_sex.setText(student.getSex());
textview_hobby.setText(student.getHobby());
imageview.setImageResource(student.getImg());
return convertView;
}
进化版:为了不建太多view占用太多内存,增加了一个ViewHolder,让它持有这几个控件,如果新建view就findid给ViewHolder并把它设置成标记,不新建就把这个标记取出来直接调用复制
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Student student=mData.get(position);
ViewHolder vh=null;

if(convertView==null){
vh=new ViewHolder(); //在这里创建对象是因为else中没有使用对象调用属性和方法,对象的有效范围只是if
convertView=minflater.inflate(R.layout.simple_adpter,null);
vh.imageview= (ImageView) convertView.findViewById(R.id.image_photo);
vh. textview_name= (TextView) convertView.findViewById(R.id.text_name);
vh. textview_sex= (TextView) convertView.findViewById(R.id.text_sex);
vh. textview_hobby= (TextView) convertView.findViewById(R.id.text_hobby);
convertView.setTag(viewHolder);
}else{
vh= (ViewHolder) convertView.getTag();
}
//共同部分
vh.textview_name.setText(student.getName());
vh.textview_sex.setText(student.getSex());
vh.textview_hobby.setText(student.getHobby());
vh.imageview.setImageResource(student.getImg());
return convertView;
}
class ViewHolder{
TextView textview_name;
TextView textview_sex;
TextView textview_hobby;
ImageView imageview;
}
现在再新建一个选择水果,在规则布局上添加一个CheckButton,因为初始化数据时为了满屏用的for循环,对象重复出现了点击一个下面一片被选中


解决方法:在for循环中创建对象
private void gettData() {   //这是自定义adapter的activity中初始化List的方法
mFruit=new ArrayList<>();

for(int i=0;i<50;i++){
mFruit.add(new Fruit("苹果",R.mipmap.apple));
mFruit.add(new Fruit("橘子",R.mipmap.orange));
mFruit.add(new Fruit("草莓",R.mipmap.berry));
}
本来出错:
caomei=new Fruit("草莓",R.mipmap.berry)
for(····){
mFruit.add(caomei);//for出来的都是一个对象
}
   在规则布局文件中写focusable屏蔽CheckBox吃掉不属于它的点击
    android:gravity="center_vertical">
<CheckBox
android:id="@+id/checkbox_fruit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false" //防止Button、CheckBox吃掉属于listView的点击事件
android:text="选择水果"/>
<ImageView
android:id="@+id/imageview_fruit"
android:layout_width="100dp"
android:layout_height="100dp"
/>
<TextView
android:id="@+id/textview_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="水果名称"/>
</LinearLayout>
源代码:(注意全局变量
/**
* Fruitadapter.java
*/
public class Fruitadapter extends BaseAdapter {
private LayoutInflater mInflater;
private List<Fruit> mFruits;
private boolean[] mManagerAllCheckedBox;//控制所有checkbox,初始值全为false

public Fruitadapter(LayoutInflater mInflater, List<Fruit> mFruits) {
this.mInflater = mInflater;
this.mFruits = mFruits;
mManagerAllCheckedBox = new boolean[mFruits.size()];//数据多少它就多少,初始化mFruit之后再初始化数组,不然空指针
}

@Override
public int getCount() {
return mFruits.size();
}

@Override
public Object getItem(int position) {

return position;
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Fruit fruit = mFruits.get(position);
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_fruit, null);
viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox_fruit);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageview_fruit);
viewHolder.textView = (TextView) convertView.findViewById(R.id.textview_name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(fruit.getName());
viewHolder.imageView.setImageResource(fruit.getImg());
viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mManagerAllCheckedBox[position] = isChecked;
notifyDataSetChanged();//来更新屏幕(一个对象创建好几遍点一个另一个不立即反应说明屏幕不刷新)
}
});
viewHolder.checkBox.setChecked(mManagerAllCheckedBox[position]);
//下一页时对象就改变了,所以没检测到点击,值是false用于刷新来自convertView的checkbox状态(不能放在监听前面,前面就不会刷新了)
return convertView;
}

public void itemposition(int position) { //在listView点击事件中调用,点一下CheckBox状态取反
mManagerAllCheckedBox[position] = !mManagerAllCheckedBox[position];//得到本行的水果对象
notifyDataSetChanged();
}

public void checkedall() { //在增加的HeaderView中的全选按钮点击时调用,全选中
for (int i = 0; i < mFruits.size(); i++) {
mManagerAllCheckedBox[i] = true;
notifyDataSetChanged();
}
}

public void fanxuan() { //在增加的FooterView中的反选按钮调用,全部反选
for (int i = 0; i < mFruits.size(); i++) {
mManagerAllCheckedBox[i] = !mManagerAllCheckedBox[i];
notifyDataSetChanged();
}
}

class ViewHolder {
ImageView imageView;
CheckBox checkBox;
TextView textView;
}
}
/**
*
FruitcheckActivity.java  
其中增加了HeaderView和FooterView
*/
public class FruitcheckActivity extends ActionBarActivity {
private ListView listView;
private List<Fruit> mFruit;
private Fruitadapter mFruitadapter;
private LayoutInflater inflater;
private View mHeaderView;
private Button mBtnCheckedAll;
private View mFooterView;
private Button mBtnFanxuan;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fruitcheck);//这个布局跟自定义时候一样里面只有一个listView
listView = (ListView) findViewById(R.id.list_fruit);
inflater = getLayoutInflater();
增加HeaderView和FooterView,其中加入全选和反选按钮,跟adapter中的规则布局一样都是关联布局文件  
mHeader View= inflater.inflate(R.layout.layout_all, null);
mBtnCheckedAll = (Button) mHeaderView.findViewById(R.id.button_checked_all);
mBtnCheckedAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFruitadapter.checkedall();
}
});
listView.addHeaderView(mHeader);
mFooter = inflater.inflate(R.layout.layout_fan, null);
mBtnFanxuan = (Button) mFooter.findViewById(R.id.button_fanxuan);
mBtnFanxuan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFruitadapter.fanxuan();
}
});
listView.addFooterView(mFooter);
 
    gettData();
mFruitadapter = new Fruitadapter(inflater, mFruit);
listView.setAdapter(mFruitadapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//listView增加一个点击事件,button不同,是itemCliklistener
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mFruitadapter.itemposition(position - 1);//adapter对象改成全局变量,把position传过去
}
});
}
private void gettData() {
mFruit = new ArrayList<>();
for (int i = 0; i < 10; i++) {
mFruit.add(new Fruit("苹果", R.mipmap.apple));
mFruit.add(new Fruit("橘子", R.mipmap.orange));
mFruit.add(new Fruit("草莓", R.mipmap.berry));
}
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值