1.先写遇到的问题:
a.ListView只显示一个item。
listview只显示一个item,并且做了listview的点击事件监听打印 Bean 对象的属性和哈希值,发现只有显示的那个 Bean 对象有属性值,其他item显示的 Bean 对象属性值为null,但是 Bean对象有唯一哈希值,说明 Bean 对象成功创建了,但是是什么原因导致其他属性值为空的呢?经过检查发现。每个对象是创建出来了,创建了第二个对象时,本来用第二个对象去引用属性值,结果用了第一个去引用属性值。
错误代码:
1 Beauty beauty = new Beauty(); 2 beauty.age = "20"; 3 beauty.name = "西施"; 4 beauty.icon = mContext.getResources().getDrawable(R.drawable.a, null); 5 arraylist.add(beauty); 6 7 Beauty beauty1 = new Beauty(); 8 beauty.age = "18"; 9 beauty.name = "貂蝉"; 10 beauty.icon = mContext.getResources().getDrawable(R.drawable.b, null); 11 arraylist.add(beauty1);
正确为:
1 Beauty beauty = new Beauty(); 2 beauty.age = "20"; 3 beauty.name = "西施"; 4 beauty.icon = mContext.getResources().getDrawable(R.drawable.a, null); 5 arraylist.add(beauty); 6 7 Beauty beauty1 = new Beauty(); 8 beauty1.age = "18"; 9 beauty1.name = "貂蝉"; 10 beauty1.icon = mContext.getResources().getDrawable(R.drawable.b, null); 11 arraylist.add(beauty1);
b.只能显示一页,滑动lLIstView时,出现了ViewHolder空指针问题。
优化自定义adapter的getView()里面的FindViewById()时,从view里获取存储的ViewHolder对象写成了局部对象,当滑动listview再次获取ViewHolder时,由于是局部对象,获取不到报空指针。
1 public View getView(int position, View convertView, ViewGroup parent) { 2 3 View view = null; 4 ViewHolder viewholder = null; 5 6 if (convertView != null) { 7 view = convertView; 8 viewholder = (ViewHolder) view.getTag();//从view里获取存储的ViewHolder,写成了局部对象。 9 } else { 10 LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 11 view = layoutInflater.inflate(item, parent, false); 12 13 //每次调用getView 都会执行FindViewById所以继续优化。 14 viewholder = new ViewHolder(); 15 viewholder.viewHolderImageview= (ImageView) view.findViewById(R.id.IV_imageview); 16 viewholder.viewHolderTextview_1 = (TextView) view.findViewById(R.id.TV_age); 17 viewholder.viewHolderTextview_2 = (TextView) view.findViewById(R.id.TV_name); 18 view.setTag(viewholder);//将viewholder存储在view中 19 } 20 }
2.自定义ListView的使用。
a.先把Context赋值为全局变量(后面会用到),在获取XML中的listview的ID。
b.创建ArrayList和Bean对象,并用ArrayList封装Bean对象。
c.创建Adapter,继承BaseAdapter。
d.listview设置显示的adapter。
e.设置listview的监听事件,实现 AdapterView.OnItemClickListener。
1 protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 setContentView(R.layout.activity_main); 4 mContext = this; 5 6 lv_1=(ListView)findViewById(R.id.lv_1); 7 ArrayList<Beauty> arraylist= BeautyUtlis.getAllBeauty(mContext); 8 9 10 MyAdapter myadapter=new MyAdapter(mContext,R.layout.item_1,arraylist); 11 lv_1.setAdapter(myadapter); 12 13 //点击事件 14 lv_1.setOnItemClickListener(this); 15 16 }
b.通过ArrayList封装Bean对象。
创建Bean。
1 public class Beauty { 2 public String age; 3 public String name; 4 public Drawable icon; 5 6 public Beauty() { 7 } 8 9 public Beauty(String age, String name, Drawable icon) { 10 this.age = age; 11 this.name = name; 12 this.icon = icon; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public void setName(String name) { 20 this.name = name; 21 } 22 23 public String getAge() { 24 return age; 25 } 26 27 public void setAge(String age) { 28 this.age = age; 29 } 30 31 public Drawable getIcon() { 32 return icon; 33 } 34 35 public void setIcon(Drawable icon) { 36 this.icon = icon; 37 } 38 }
创建ArrayList集合用于封装Bean。循环是为了显示更多条目。
1 public class BeautyUtlis { 2 public static ArrayList<Beauty> getAllBeauty(Context mContext) { 4 5 ArrayList<Beauty> arraylist = new ArrayList<>(); 6 7 for(int i=0;i<3;i++) { 8 Beauty beauty = new Beauty(); 9 beauty.age = "20"; 10 beauty.name = "西施"; 11 beauty.icon = mContext.getResources().getDrawable(R.drawable.a, null); 12 arraylist.add(beauty); 13 14 Beauty beauty1 = new Beauty(); 15 beauty1.age = "18"; 16 beauty1.name = "貂蝉"; 17 beauty1.icon = mContext.getResources().getDrawable(R.drawable.b, null); 18 arraylist.add(beauty1); 19 20 21 Beauty beauty2 = new Beauty(); 22 beauty2.age = "22"; 23 beauty2.name = "杨贵妃"; 24 beauty2.icon = mContext.getResources().getDrawable(R.drawable.c, null); 25 arraylist.add(beauty2); 26 27 28 Beauty beauty3 = new Beauty(); 29 beauty3.age = "20"; 30 beauty3.name = "阿科"; 31 beauty3.icon = mContext.getResources().getDrawable(R.drawable.d, null); 32 arraylist.add(beauty3); 33 34 } 35 return arraylist; 36 } 37 }
c.创建Adapter,继承BaseAdapter,通过自定义的构造方法传Context,item ID,ArrayList封装的Bean对象。
1 public class MyAdapter extends BaseAdapter { 2 3 4 private final Context mContext; 5 private final ArrayList<Beauty> arraylist; 6 private final int item; 7 8 9 public MyAdapter(Context mContext, int item_1, ArrayList<Beauty> araylist) { 10 this.mContext = mContext; 11 this.arraylist = araylist; 12 this.item = item_1; 13 } 14 15 //listview 显示多少个条目 16 @Override 17 public int getCount() { 18 return arraylist.size(); 19 } 20 21 22 //根据postiion获取条目对应的Bean数据 23 @Override 24 public Object getItem(int position) { 25 return arraylist.get(position); 26 } 27 28 //获取position条目的ID 29 @Override 30 public long getItemId(int position) { 31 return position; 32 } 33 34 35 /** 36 * getview:告诉listview条目上显示的内容;返回一个View对象作为条目上的内容展示,该方法返回什么样的view,Listview的条目上就显示什么样的view。38 * //屏幕上每显示一个条目getview方法就会被调用一次;
convertView:曾经使用过的view对象,可以被重复使用,使用前要判断。 39 **/ 40 @Override 41 public View getView(int position, View convertView, ViewGroup parent) { 42 43 View view = null; 44 ViewHolder viewholder = null; 45
//判断convertView是否为空,为空创建新的View,不为空则复用被推出页面外的view 46 if (convertView != null) { 47 view = convertView; 48 viewholder = (ViewHolder) view.getTag();//从view里获取存储的ViewHolder 49 } else { 50 LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 51 view = layoutInflater.inflate(item, parent, false); 52 53 //每次调用getView 都会执行FindViewById所以继续优化。 54 viewholder = new ViewHolder(); 55 viewholder.viewHolderImageview= (ImageView) view.findViewById(R.id.IV_imageview); 56 viewholder.viewHolderTextview_1 = (TextView) view.findViewById(R.id.TV_age); 57 viewholder.viewHolderTextview_2 = (TextView) view.findViewById(R.id.TV_name); 58 view.setTag(viewholder);//将viewholder存储在view中 59 } 60 //获取Bean对象 61 62 Beauty beauty = arraylist.get(position); 63 64 viewholder.viewHolderImageview.setImageDrawable(beauty.getIcon()); 65 viewholder.viewHolderTextview_1.setText(beauty.getAge()); 66 viewholder.viewHolderTextview_2.setText(beauty.getName()); 80 return view; 81 } 82 83 //优化FindVIewById 84 class ViewHolder { 85 ImageView viewHolderImageview; 86 TextView viewHolderTextview_1; 87 TextView viewHolderTextview_2; 88 } 89 }
d.listview设置显示的adapter。
1 lv_1.setAdapter(myadapter);
e.设置listview的监听事件,实现 AdapterView.OnItemClickListener。简单打印。
1 { 2 ......... 3 lv_1.setOnItemClickListener(this); 4 5 } 6 7 @Override 8 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 9 //获取条目对应的对象 10 Beauty beauty = (Beauty) parent.getItemAtPosition(position);
11 Toast.makeText(mContext,"点击了第"+position+"位置,"+"姓名叫:"+beauty.name+",年龄是:"+beauty.age,Toast.LENGTH_LONG).show(); 12 13 }