csschn

Android,你等等我。。。

导航

【实战】初识ListView及提高效率

简介:

  ListView是手机上最常用的控件之一,几乎所有的程序都会用到,手机屏幕空间有限,当需要显示大量数据的时候,就需要借助ListView来实现,允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时原有的数据将滚动出去。

 一、使用准备好的data数组来显示ListView

  1. 新建项目,修改activity_main.xml中的代码,增加ListView控件,简单设置属性
     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:paddingBottom="@dimen/activity_vertical_margin"
     6     android:paddingLeft="@dimen/activity_horizontal_margin"
     7     android:paddingRight="@dimen/activity_horizontal_margin"
     8     android:paddingTop="@dimen/activity_vertical_margin"
     9     tools:context="com.example.listviewtest.MainActivity" >
    10 
    11     <ListView
    12         android:id="@+id/list_view"
    13         android:layout_width="match_parent"
    14         android:layout_height="match_parent"
    15     />
    16 
    17 </RelativeLayout>
  2. 在主活动MainActivity.java中新建数据数组data,新建适配器,设置适配器显示
     1 package com.example.listviewtest;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.widget.ArrayAdapter;
     6 import android.widget.ListView;
     7 public class MainActivity extends Activity {
     8 
     9     //建立私有数组来存储要显示的数据
    10     private String[] data = {"Apple","Banana","Orange","Watermelon","pear","Grape","Pineapple","Strawberry","Cherry","Mango"
    11                             ,"Apple","Banana","Orange","Watermelon","pear","Grape","Pineapple","Strawberry","Cherry","Mango"};
    12     
    13     @Override
    14     protected void onCreate(Bundle savedInstanceState) {
    15         super.onCreate(savedInstanceState);
    16         setContentView(R.layout.activity_main);
    17         
    18         //新建适配器来转换数据
    19         ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,data);
    20         
    21         //实例化ListView
    22         ListView listView = (ListView) findViewById(R.id.list_view);
    23         
    24         //给listView设置适配器,将ListView和数据联系起来
    25         listView.setAdapter(adapter);
    26     }
    27     
    28 }

 二、定制ListView的界面,可以设置图片等、更加美观

  1. 新建实体类,来存放要显示的数据,这里使用的水果列表
     1 package com.example.listviewtest;
     2 
     3 //存放水果信息的类
     4 public class Fruit {
     5     private String name ;//定义私有变量存储水果名称
     6     private int imageId ;//定义私有变量存储水果图片ID
     7 
     8     //定义构造方法来初始化
     9     public  Fruit(String name , int imageId ) {
    10         // TODO Auto-generated method stub
    11         this.name = name;
    12         this.imageId = imageId;
    13     }
    14     
    15     //获取名称
    16     public String getName() {
    17         return name;
    18     }
    19     //获取图片ID
    20     public int getImageId()
    21     {
    22         return imageId;
    23     }
    24 }
    Fruit
  2. 为ListView的子项指定一个自定义布局fruit_item.xml,ImageView显示水果图片,TextView显示水果名称
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="horizontal" >
     6     
     7     <ImageView 
     8         android:id="@+id/fruit_image"
     9         android:layout_width="50sp"
    10         android:layout_height="50sp"/>
    11 
    12     <TextView 
    13         android:id="@+id/fruit_name"
    14         android:layout_width="wrap_content"
    15         android:layout_height="wrap_content"
    16         android:layout_gravity="center"居中显示17         android:layout_marginLeft="10dip" 距离左侧10dip   />
    18 </LinearLayout>
  3. 自定义适配器继承于ArrayAdapter,将泛型指定为Fruit类
     1 package com.example.listviewtest;
     2 
     3 import java.util.List;
     4 import android.content.Context;
     5 import android.view.LayoutInflater;
     6 import android.view.View;
     7 import android.view.ViewGroup;
     8 import android.widget.ArrayAdapter;
     9 import android.widget.ImageView;
    10 import android.widget.TextView;
    11 
    12 public class FruitAdapter extends ArrayAdapter<Fruit> {
    13     //定义地址路径    resourceId
    14     private int resourceId;
    15     
    16     //重写父类的构造方法,传入上下文,ListView子布局ID和数据传进来;
    17     public FruitAdapter(Context context,int textViewResource,List<Fruit> object) {
    18         // TODO Auto-generated constructor stub
    19         super(context , textViewResource , object);
    20         resourceId = textViewResource;
    21     }
    22     
    23     //重写getView方法,返回View
    24     @Override
    25     public View getView(int position, View convertView, ViewGroup parent) {
    26         
    27         //获取当前页面的Fruit实例,根据屏幕上的菜单滚动得到
    28         Fruit fruit = getItem(position);
    29         
    30         //使用Layoutinflater为这个子项加载我们传入的布局(resourceId),
    31         View view = LayoutInflater.from(getContext()).inflate(resourceId, null);
    32         
    33         //分别获取子布局中ImageView和TextView的实例
    34         ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
    35         TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
    36         
    37         //调用控件ImageView实例的setImageResource设置图片,TextView的setText方法设置文字;
    38         fruitImage.setImageResource(fruit.getImageId());
    39         fruitName.setText(fruit.getName());
    40         
    41         //返回View
    42         return view;
    43         
    44     }
    45 }
    FruitAdapter类
  4. 重写MainActivity.java文件,
     1 package com.example.listviewtest;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 import com.example.listviewtest.Fruit;
     6 import android.app.Activity;
     7 import android.os.Bundle;
     8 import android.widget.ListView;
     9 public class MainActivity extends Activity {
    10 
    11     //建立一个集合来存储实体类,实际上是水果的列表
    12     private List<Fruit> fruitList = new ArrayList<Fruit>();
    13     @Override
    14     protected void onCreate(Bundle savedInstanceState) {
    15         super.onCreate(savedInstanceState);
    16         setContentView(R.layout.activity_main);
    17 
    18         //实例化ListView控件为listView
    19         ListView listView = (ListView) findViewById(R.id.list_view);
    20         
    21         //利用自定义方法初始化水果数据
    22         initFruits();
    23         
    24         //实例化适配器FruitAdapter,传入上下文、子布局、水果列表
    25         FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList);
    26         
    27         //为listView设置适配器,联系ListView和数据
    28         listView.setAdapter(adapter);
    29     }
    30     
    31     //自定义方法初始化水果数据
    32     private void initFruits() {
    33         
    34         //实例化水果对象;
    35         Fruit apple = new Fruit("Apple",R.drawable.apple_pic);
    36         
    37         //将对象传入自定义列表中
    38         fruitList.add(apple);
    39         
    40         //以下和上面是一个道理
    41         Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
    42         fruitList.add(banana);
    43         Fruit orange = new Fruit("Orange",R.drawable.orange_pic);
    44         fruitList.add(orange);
    45         Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon_pic);
    46         fruitList.add(watermelon);
    47         Fruit pear = new Fruit("Pear",R.drawable.pear_pic);
    48         fruitList.add(pear);
    49         Fruit grape = new Fruit("Grape",R.drawable.grape_pic);
    50         fruitList.add(grape);
    51         Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
    52         fruitList.add(pineapple);
    53         Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
    54         fruitList.add(strawberry);
    55         Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
    56         fruitList.add(cherry);
    57         Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
    58         fruitList.add(mango);
    59     }
    60 
    61     
    62 }
    MainActivity.java
  5. 显示效果(右键查看图像看大图):

 三、提升ListView的运行效率,基于上面二中的例子

  主要解决的是:   1、在getView中每次都加载布局

          2、getView中每次都要实例化控件的实例

  1. 优化一:通过判断FruitAdapter中的getView方法中的convertView是否为空进行优化;(红色为修改部分)
     1 package com.example.listviewtest;
     2 
     3 import java.util.List;
     4 import android.content.Context;
     5 import android.view.LayoutInflater;
     6 import android.view.View;
     7 import android.view.ViewGroup;
     8 import android.widget.ArrayAdapter;
     9 import android.widget.ImageView;
    10 import android.widget.TextView;
    11 
    12 public class FruitAdapter extends ArrayAdapter<Fruit> {
    13     //定义地址路径    resourceId
    14     private int resourceId;
    15     
    16     //重写父类的构造方法,传入上下文,ListView子布局ID和数据传进来;
    17     public FruitAdapter(Context context,int textViewResource,List<Fruit> object) {
    18         // TODO Auto-generated constructor stub
    19         super(context , textViewResource , object);
    20         resourceId = textViewResource;
    21     }
    22     
    23     //重写getView方法,返回View
    24     @Override
    25     public View getView(int position, View convertView, ViewGroup parent) {
    26         
    27         //获取当前页面的Fruit实例,根据屏幕上的菜单滚动得到
    28         Fruit fruit = getItem(position);
    29         
    30         //新建View对象
    31         View view ;
    32         
    33         //判断convertView对象是否为空,如果为空就重新加载;
    34         if(convertView == null)
    35         {
    36             //使用Layoutinflater为这个子项加载我们传入的布局(resourceId),
    37             view = LayoutInflater.from(getContext()).inflate(resourceId, null);
    38         }
    39         else//如果不为空,则重新调用convertView;不必重新加载
    40         {
    41             view = convertView;
    42         }
    43         
    44         //分别获取子布局中ImageView和TextView的实例
    45         ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
    46         TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
    47         
    48         //调用控件ImageView实例的setImageResource设置图片,TextView的setText方法设置文字;
    49         fruitImage.setImageResource(fruit.getImageId());
    50         fruitName.setText(fruit.getName());
    51         
    52         //返回View
    53         return view;
    54         
    55     }
    56 }
  2. 优化二:借助ViewHolder来对获取控件实例进行优化,修改Fruit中的代码,(对比上面的优化一,红色为修改部分)
     1 package com.example.listviewtest;
     2 
     3 import java.util.List;
     4 import android.content.Context;
     5 import android.view.LayoutInflater;
     6 import android.view.View;
     7 import android.view.ViewGroup;
     8 import android.widget.ArrayAdapter;
     9 import android.widget.ImageView;
    10 import android.widget.TextView;
    11 
    12 public class FruitAdapter extends ArrayAdapter<Fruit> {
    13     //定义地址路径    resourceId
    14     private int resourceId;
    15     
    16     //重写父类的构造方法,传入上下文,ListView子布局ID和数据传进来;
    17     public FruitAdapter(Context context,int textViewResource,List<Fruit> object) {
    18         // TODO Auto-generated constructor stub
    19         super(context , textViewResource , object);
    20         resourceId = textViewResource;
    21     }
    22     
    23     //重写getView方法,返回View
    24     @Override
    25     public View getView(int position, View convertView, ViewGroup parent) {
    26         
    27         //获取当前页面的Fruit实例,根据屏幕上的菜单滚动得到
    28         Fruit fruit = getItem(position);
    29         
    30         //新建View对象
    31         View view ;
    32         
    33         //声明
    34         ViewHolder viewHolder;
    35         
    36         //判断convertView对象是否为空,如果为空就重新加载;
    37         if(convertView == null)
    38         {
    39             //使用Layoutinflater为这个子项加载我们传入的布局(resourceId),
    40             view = LayoutInflater.from(getContext()).inflate(resourceId, null);
    41             //实例化一个ViewHolder
    42             viewHolder = new ViewHolder();
    43             //将控件的实例都存在ViewHolder中
    44             viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
    45             viewHolder.fruitname = (TextView) view.findViewById(R.id.fruit_name);
    46             //吧ViewHolder存储在View中;
    47             view.setTag(viewHolder);
    48         }
    49         else//如果不为空,则重新调用convertView;不必重新加载
    50         {
    51             view = convertView;
    52             //重新获取ViewHolder
    53             viewHolder = (ViewHolder) view.getTag();
    54         }
    55         
    56         //分别获取子布局中ImageView和TextView的实例
    57 //        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
    58 //        TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
    59         
    60         //调用控件ImageView实例的setImageResource设置图片,TextView的setText方法设置文字;
    61 //        fruitImage.setImageResource(fruit.getImageId());
    62 //        fruitName.setText(fruit.getName());
    63         
    64         //在ViewHolder中完成设置
    65         viewHolder.fruitImage.setImageResource(fruit.getImageId());
    66         viewHolder.fruitname.setText(fruit.getName());
    67         
    68         //返回View
    69         return view;
    70         
    71     }
    72 }
    73 class ViewHolder {
    74     ImageView fruitImage;
    75     TextView fruitname;
    76 }

     

总结:通过上面两部的优化,已经很大程度上提高了ListView的运行效率了;

最终效果图:

 

 

追加:为ListView设置点击事件;

  在MainActivity中加入ListView的监听事件

 1 listView.setOnItemClickListener(new OnItemClickListener() {
 2 
 3             @Override
 4             public void onItemClick(AdapterView<?> parent, View view,
 5                     int position, long id) {
 6                 
 7                 //获取当前点击的Fruit对象
 8                 Fruit fruit = fruitList.get(position);
 9                 
10                 //利用Toast提示点击事件
11                 Toast.makeText(MainActivity.this, "You Clicked The"+fruit.getName(), Toast.LENGTH_SHORT).show();
12             }
13             
14         });

 效果图:

posted on 2016-03-06 13:39  csschn  阅读(451)  评论(0编辑  收藏  举报