8/25/自定义Adapter缓存与时间优化/ListView、checkBox点击监听/addHeaderView/addFootView
2015-08-25 19:27
351 查看
自定义Adapter缓存与时间优化
ListView、checkBox点击监听
addHeaderView与addFootView
自定义Adapter中的需要注意的地方
1.首先看昨天的写的代码public View getView(int position, View convertView, ViewGroup parent) { View view=mInflater.inflate(R.layout.item_simple_adapter, null); Student student=mData.get(position); ImageView imageView= (ImageView) view.findViewById(R.id.imageview_photo); TextView textview_name= (TextView) view.findViewById(R.id.textview_name); TextView textview_age= (TextView) view.findViewById(R.id.textview_age); TextView textview_sex= (TextView) view.findViewById(R.id.textview_sex); TextView textview_hobby= (TextView) view.findViewById(R.id.textview_hobby); imageView.setImageResource(student.getImg()); textview_name.setText(student.getName()); textview_age.setText(student.getAge()); textview_sex.setText(student.getSex()); textview_hobby.setText(student.getHobby()); return view; }
这种方法写的坏处在于:有多少个数据就要加载多少个view,如果数据量特别大时,会占用很多的内存,容易导致程序崩溃,同时每次创建一个View是都会调用findViewById这个函数,当数据量特别大时也会占用很多的时间,因此需要调用其他的方法来加载大数据。
2.再来看看下面的代码
@Override public View getView(int position, View convertView, ViewGroup parent) { Student student = mData.get(position); ViewHolder vh = null; /*** * convertView是指没有显示到屏幕上的界面 * 判断有没有下拉或者上拉操作,(初始的的时候是没有上拉或者下拉操作的,如果一个界面能显示10条信息 * 那么就会创建十次view,如果不进行判断那么就会有多少条数据就会生成多少个view,这样的方法不仅耗时 * 而且贴别占用内存,有很多数据时就会导致程序崩溃,因此利用缓存机制,convertView就是预缓存的View * 在进行上拉操作时,第一个view就会出去,下面缓存的view就会进入界面,而出去的view不会消失而是变成 * convertView清空里面的信息重新加载新的信息变成缓存,这样就只需要创建几个view就可以显示很多条数据 * 而不会创建很多的view,降低了内存的占用,同时上拉操作也是一样的,创建的这几个界面就像是一个圆盘 * 一样滚动显示和缓存view) */ if (convertView == null) { convertView = mInflater.inflate(R.layout.item_simple_adapter, null); vh=new ViewHolder(); //对vh赋初始值 vh.imageView = (ImageView) convertView.findViewById(R.id.imageview_photo); vh.textview_name = (TextView) convertView.findViewById(R.id.textview_name); vh.textview_age = (TextView) convertView.findViewById(R.id.textview_age); vh.textview_sex = (TextView) convertView.findViewById(R.id.textview_sex); vh.textview_hobby = (TextView) convertView.findViewById(R.id.textview_hobby); convertView.setTag(vh); //将所有vh的对象打包 Log.d("convertView","创建新的view"); } else { /*** * 当有下拉或者上拉操作时,即要显示缓存的convertView时,调用前面的打包好的ViewHolder不再创建新 * 的view以及进行findViewById的操作(相当于直接拿来个模板进行使用) */ vh = (ViewHolder) convertView.getTag(); Log.d("convertView","加载已创建的view"); } //给vh的对象赋值 vh.imageView.setImageResource(student.getImg()); vh.textview_name.setText(student.getName()); vh.textview_age.setText(student.getAge()); vh.textview_sex.setText(student.getSex()); vh.textview_hobby.setText(student.getHobby()); return convertView; } /*** * 创建一个view的持有者里面包含了所有要显示的信息 */ class ViewHolder { TextView textview_name; TextView textview_age; TextView textview_sex; TextView textview_hobby; ImageView imageView; }
上面的代码中创建了一个类 ViewHolder,用于存放数据模板的中的名称,convertView指的是缓存的View,上面的代码中有详细的解释,在这里就不在过多的解释了
ListView和checkBox的点击监听
1.如果在有checkBox的ListView上进行点击监听的话,由于checkBox的级别比较高,从底层传过来的点击事件会收先通过checkBox的处理,但是checkBox对点击的处理仅限于checkBox的那一小块区域(就是checkBox图标区域)对于ListView的其他区域传递过来的信号不做任何处理直接丢掉,因此会出现ListView的点击监听失效的情况(点击checkBox所在的View不会有点击事件的发生),这是需要在checkBox的xml中加入android:focusable="false" <!--这一句的作用是将除了checkbox的范围之外的点击不做任何处理,抛给其他点击事件 -->
addHeaderView和addFootView
1.addHeaderView是向ListView的首段即第一个View中添加一个View,但是添加过后需要注意的是在点击点击监听的事件时,会把他默认为ListView的第一个标签即默认他的position为0,因此在选其他View时需要把position-1这样才会正常的选中和显示,在其他的地方不用position-1(这是ListView的缺陷所在)2.addFootView是向ListView的末尾添加一个View
3.addHeaderView和addFootView实现代码如下:
//在末尾添加button mFootView =mInflater.inflate(R.layout.hero_foot,null); mBtnFootView= (Button) mFootView.findViewById(R.id.button_all_fanxuan); mBtnFootView.setOnClickListener(new View.OnClickListener() { @Override //反选 public void onClick(View v) { mAdapter.checkedFanxuan(); } }); mListView.addFooterView(mFootView); //在前面添加button mHeaderView=mInflater.inflate(R.layout.hero_header,null); mListView.addHeaderView(mHeaderView); mBtnHeaderView= (Button) mHeaderView.findViewById(R.id.button_all_check); mBtnHeaderView.setOnClickListener(new View.OnClickListener() { @Override //选择全部 public void onClick(View v) { mAdapter.checkAll(); } });
自定义Adapter全部代码如下
XML:布局文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical"> <!-- android:focusable="false" 这一句的作用是将除了checkbox的范围之外的点击不做任何处理,抛给其他点击事件 --> <CheckBox android:id="@+id/checkbox_hero" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" /> <ImageView android:id="@+id/imageview_hero" android:layout_width="100dp" android:layout_height="100dp" /> <TextView android:id="@+id/textview_hero" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="英雄" android:textColor="@color/nattierblue" /> </LinearLayout> </RelativeLayout> XML文件AddHeaderView: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button_all_check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="全选"/> </LinearLayout> XML文件AddFootView: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button_all_fanxuan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="反选"/> </LinearLayout> model文件: package com.my.twentyoneaug.model; /** * Created by Administrator on 2015/8/25. */ public class Hero { private String name; private int img; private boolean isChecked; public Hero(String name, int img) { this.name = name; this.img = img; } public boolean isChecked() { return isChecked; } public void setIsChecked(boolean isChecked) { this.isChecked = isChecked; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImg() { return img; } public void setImg(int img) { this.img = img; } } 自定义Adapter: package com.my.twentyoneaug.adapter; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; import com.my.twentyoneaug.R; import com.my.twentyoneaug.model.Hero; import java.util.List; /** * Created by Administrator on 2015/8/25. */ public class HeroAdapter extends BaseAdapter{ private List<Hero> mHero; private LayoutInflater mInflater; boolean [] mMangerAllCheckBox; public HeroAdapter(List<Hero> mHero, LayoutInflater mInflater) { this.mHero = mHero; this.mInflater = mInflater; mMangerAllCheckBox=new boolean[mHero.size()]; } /** * 全选 */ public void checkAll(){ for (int i = 0; i <mMangerAllCheckBox.length ; i++) { mMangerAllCheckBox[i]=true; notifyDataSetChanged(); } // for (int i = 0; i < mHero.size(); i++) { // mHero.get(i).setIsChecked(true); // notifyDataSetChanged(); // } } /*** * 反选 */ public void checkedFanxuan(){ for (int i = 0; i <mMangerAllCheckBox.length ; i++) { mMangerAllCheckBox[i]=!mMangerAllCheckBox[i]; notifyDataSetChanged(); } // for (int i = 0; i < mHero.size(); i++) { // mHero.get(i).setIsChecked(!mHero.get(i).isChecked()); // notifyDataSetChanged(); // } } /*** * 该方法用于改变position的boolean值,然后刷新数据, * @param position 传入点击的位置 */ public void slectOnClick(int position){ mMangerAllCheckBox[position]=!mMangerAllCheckBox[position]; // mHero.get(position).setIsChecked(!mHero.get(position).isChecked());//和上面的注释效果是一样的 notifyDataSetChanged(); } @Override public int getCount() { return mHero.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) { ViewHolder vh=null; if(convertView==null){ convertView=mInflater.inflate(R.layout.hero_adapter,null); vh=new ViewHolder(); vh.checkBox= (CheckBox) convertView.findViewById(R.id.checkbox_hero); vh.imageView= (ImageView) convertView.findViewById(R.id.imageview_hero); vh.textView= (TextView) convertView.findViewById(R.id.textview_hero); convertView.setTag(vh); }else{ vh= (ViewHolder) convertView.getTag(); } Hero hero=mHero.get(position); vh.textView.setText(hero.getName()); vh.imageView.setImageResource(hero.getImg()); /*** * checkBox的点击监听,如果被点击到那么isChecked就会变为true,Log.d就是输出这个变化 * 然后 */ vh.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Log.d("hero","选择框发生变化"+isChecked); mMangerAllCheckBox[position]=isChecked; // mHero.get(position).setIsChecked(isChecked); //得到点击的位置然后将对应位置的值设为isChecked notifyDataSetChanged(); //刷新界面,重新调用getView方法 } }); vh.checkBox.setChecked(mMangerAllCheckBox[position]); // vh.checkBox.setChecked(hero.isChecked()); return convertView; } class ViewHolder{ ImageView imageView; TextView textView; CheckBox checkBox; } } Activity: package com.my.twentyoneaug; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import com.my.twentyoneaug.adapter.HeroAdapter; import com.my.twentyoneaug.model.Hero; import java.util.ArrayList; import java.util.List; public class HeroActivity extends AppCompatActivity { private List<Hero> mHero; private ListView mListView; private HeroAdapter mAdapter; private LayoutInflater mInflater; private View mFootView; private Button mBtnFootView; private View mHeaderView; private Button mBtnHeaderView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hero); mListView= (ListView) findViewById(R.id.listview_hero); mInflater=getLayoutInflater(); initData(); mAdapter=new HeroAdapter(mHero,mInflater); //在末尾添加button mFootView =mInflater.inflate(R.layout.hero_foot,null); mBtnFootView= (Button) mFootView.findViewById(R.id.button_all_fanxuan); mBtnFootView.setOnClickListener(new View.OnClickListener() { @Override //反选 public void onClick(View v) { mAdapter.checkedFanxuan(); } }); mListView.addFooterView(mFootView); //在前面添加button mHeaderView=mInflater.inflate(R.layout.hero_header,null); mListView.addHeaderView(mHeaderView); mBtnHeaderView= (Button) mHeaderView.findViewById(R.id.button_all_check); mBtnHeaderView.setOnClickListener(new View.OnClickListener() { @Override //选择全部 public void onClick(View v) { mAdapter.checkAll(); } }); //添加自定义Adapter mListView.setAdapter(mAdapter); /*** * 添加addHeaderView以后ListView中的position必须要减去一,因为ListView会默认加入头部的View为第一个 * 即id为0,因此要正确的选择必须要将position-1,才可以能正常选中,否则会出现点击第一个缺选中了第二个 * 的情况。 */ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Log.d("hero","选择的英雄是:"+mHero.get(position-1).getName()); mAdapter.slectOnClick(position-1);//调用slectOnClick方法将position传入 } }); } private void initData() { mHero=new ArrayList<>(); /*** * 添加数据使用for循环时要用下面的代码否则会出错。下面的代码是每次循环都创建9个新的对象 * 如果将创建对象放到for循环的外面,在for循环里面只进行添加,那么就会导致在选择其中的一个的时候, * 例如选择vn那么所哟的vn都会被选中 */ for(int i=0;i<5;i++){ Hero vn=new Hero("暗夜猎手:薇恩",R.mipmap.vn); Hero ez=new Hero("探险家:伊泽瑞尔",R.mipmap.ez); Hero amumu=new Hero("殇之木乃伊:阿木木",R.mipmap.amumu); Hero akali=new Hero("幻影之拳:阿卡丽",R.mipmap.akli); Hero eyun=new Hero("赏金猎人:厄运小姐",R.mipmap.eyun); Hero ixi=new Hero("寒冰射手:艾希",R.mipmap.ixi); Hero kuqi=new Hero("英勇投弹手:库奇",R.mipmap.kuqi); Hero timo=new Hero("迅捷斥候:提莫",R.mipmap.timo); Hero kaitelin=new Hero("皮城女警:凯特琳",R.mipmap.kaitelin); mHero.add(vn); mHero.add(ez); mHero.add(amumu); mHero.add(akali); mHero.add(eyun); mHero.add(ixi); mHero.add(kuqi); mHero.add(timo); mHero.add(kaitelin); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_hero, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
相关文章推荐
- hdu 3268 Columbus’s bargain SPFA
- python中调用函数
- 在Ubuntu上编译caffe三部曲(CPU模式)
- windows(32位 64位)下python安装mysqldb模块
- IOS学习之iOS开发UI篇—Button基础
- 简易nagios安装
- Html.DropDownList
- 简易nagios安装
- sendmail服务器的安装
- Html.DropDownList
- 老王赛马
- ubuntu登录自动运行脚本
- 题目1112:拦截导弹
- Tiling POJ 2506
- 菜鸟学前端之遍寻名师
- Number Sequence(POJ--1019
- POJ 题目3415 Common Substrings(后缀数组+栈,求可以匹配到的长度大于k的公共子串个数)
- 代理模式和装饰模式
- 时间四象限
- 数据库大型应用解决方案总结