zoukankan      html  css  js  c++  java
  • 【实战】初识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         });

     效果图:

  • 相关阅读:
    URLOS用户福利:申请免费的泛域名(通配符域名)SSL证书
    主机管理面板LuManager以Apache2协议开源发布,可用作商业用途
    微服务设计概览
    使用SpringBoot搭建Web项目
    公共方法整合(四)数组相关
    阿里云短信整合封装类库
    高德地图接口使用整理
    公共方法整合(三)时间相关方法
    PHP 服务端友盟推送
    html 录音并上传
  • 原文地址:https://www.cnblogs.com/csschn/p/5247242.html
Copyright © 2011-2022 走看看