ListView与Adapter

ListView是用来交互和展示数据的,但是数据的类型很多,如果让ListView为每一种数据都进行适配的话那么ListView是比较臃肿的,所以就需要Adapter去帮助我们适配数据源。

Adapter是一个接口,Adapter常用的实现类如下
ArrayAdapter: 简单,易用的Adapter,通常用于将数组或者List集合的多个值包装成多个列表项。

SimpleAdapter: 并不简单,功能强大的Adapter,可用于将List集合的多个对象包装成多个列表项。

SimpleCursorAdapter:与SimpleAdapter基本相似,只是用于包装Cursor提供的数据。

BaseAdapter: 通常用于被扩展。扩展BaseAdapter可以对各列表项进行最大限度的定制。

listView与ArrayAdapter

使用步骤:
1. 创建并绑定ListView。
2. 创建ArrayAdapter。
3. 设置ListView的Adapter。

ArrayAdapter有两个构造方法:
ArrayAdapter(Context context, int textViewResourceId, List objects)
ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
其中resource用于布局文件资源。textViewResourceId设置TextView样式。

textViewResourceId常用的参数为:
simple_list_item_1: 每个列表项都是一个普通的TextView。
simple_list_item_2: 有两个TextView,分两行显示。
simple_list_item_multiple_choice: 每个列表项都带多选框。
simple_list_item_single_choice :每个列表项都带单选框。

示例程序
这里写图片描述

public class MainActivity extends Activity {

    private String[] data = {"apple", "banana", "orange", "watermelon", "pear"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1, data);

        ListView listView = (ListView) findViewById(R.id.list_view);
        listView.setAdapter(adapter);

    }


}

xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</LinearLayout>

ListView与SimpleAdapter

通过ArrayAdapter实现Adapter虽然简单,但是ArrayAdapter得功能比较有限。如果需要实现更复杂的功能就需要使用SimpleAdapter了。
SimpleAdapter的构造方法为:

public SimpleAdapter(Context context, List<? extends Map<String, ?>> data,
            @LayoutRes int resource, String[] from, @IdRes int[] to)

第二个参数: 该集合中每一个Map<String, ?> 对象生成一个列表项。
第三个参数: 指定一个界面布局的ID。
第四个参数: 决定提取Map<String , ?> 中的对象的哪些key对应的value来生成列表项。
第五个参数: 决定填充哪些组件。

示例程序
这里写图片描述

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></ListView>
</LinearLayout>

新建一个simple_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/header"
        android:paddingLeft="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/name"
            android:textSize="20dp"
            android:textColor="#f0f"
            android:paddingLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/desc"
            android:textSize="14dp"
            android:paddingLeft="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

MainActivity

public class MainActivity extends Activity {

    private String[] name = {"apple", "banana", "orange", "watermelon", "pear"};
    private String[] descs = {"苹果好吃", "香蕉好吃", "橘子好处", "西瓜好吃", "梨好吃"};
    //随便找的图标
    private int[] imageId = new int[]{R.drawable.ic_launcher, R.drawable.ic_launcher,
            R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);

        List<Map<String, Object>> listItems = new ArrayList<>();
        for (int i = 0; i < name.length; i++) {
            Map<String, Object> listItem = new HashMap<>();
            listItem.put("header", imageId[i]);
            listItem.put("name", name[i]);
            listItem.put("desc", descs[i]);
            listItems.add(listItem);
        }

        SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.simple_item,
                new String[]{"name", "header", "desc"},
                new int[]{R.id.name, R.id.header, R.id.desc});
        ListView list = (ListView) findViewById(R.id.list_view);
        list.setAdapter(simpleAdapter);


    }
}

扩展BaseAdapter

扩展BaseAdapter需要重写4个方法。
getCount():该方法的返回值控制该Adapter将会包含多少个列表项。
getItem(int position):该方法的返回值决定第position处的列表项的内容。
getItemId(int position):该方法的返回值决定第position处的列表项的ID。
getView(int position, View convertView, ViewGroup parent):这里最重要的方法,该方法的返回值决定第position处的列表项组件。

public class MyAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return null;
    }
}
getView的优化

要理解getView的优化首先应理解 Recycle机制。这里推荐郭霖的 Android ListView工作原理完全解析,带你从源码的角度彻底理解
没有任何优化:

@Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View item = mInflater.inflate(R.layout.list_item, null);
            ImageView img = (ImageView)item.findViewById(R.id.img) 
            TextView title = (TextView)item.findViewById(R.id.title);
            TextView info = (TextView)item.findViewById(R.id.info);
            img.setImageResource(R.drawable.ic_launcher);
            title.setText("Hello");
            info.setText("world");

            return item;
        }

每加载一个数据时都会重新创建View和绑定资源操作。一旦数据量多的时候会严重影响性能。

优化一:利用缓存中的View也就是convertView

public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null)
            {
                convertView = mInflater.inflate(R.layout.list_item, null);
            }

            ImageView img = (ImageView)convertView.findViewById(R.id.img) 
            TextView title = (TextView)convertView.findViewById(R.id.title);
            TextView info = (TextView)ConvertView.findViewById(R.id.info);
            img.setImageResource(R.drawable.ic_launcher);
            title.setText("Hello");
            info.setText("world");

            return convertView;
        }

优化二:利用静态类优化绑定资源的操作

//在外面先定义,ViewHolder静态类
    static class ViewHolder
    {
        public ImageView img;
        public TextView title;
        public TextView info;
    }
//然后重写getView
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if(convertView == null)
            {
                holder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.list_item, null);
                holder.img = (ImageView)item.findViewById(R.id.img) 
                holder.title = (TextView)item.findViewById(R.id.title);
                holder.info = (TextView)item.findViewById(R.id.info);
                convertView.setTag(holder);
            }else
            {
                holder = (ViewHolder)convertView.getTag();
                holder.img.setImageResource(R.drawable.ic_launcher);
                holder.title.setText("Hello");
                holder.info.setText("World");
            }

            return convertView;
        }

示例程序
这里写图片描述

activicy_main和simple_item直接用simpleAdapter示例程序的。

MainActivity:

public class MainActivity extends Activity {

    private List<Map<String, Object>> data;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);

        data = getData();
        MyAdapter myAdapter = new MyAdapter(this);
        ListView list = (ListView) findViewById(R.id.list_view);
        list.setAdapter(myAdapter);
    }

    private List<Map<String, Object>> getData(){
        List<Map<String, Object>> listItems = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            Map<String, Object> listItem = new HashMap<>();
            listItem.put("header", R.drawable.ic_launcher);
            listItem.put("name", i + "Android机器人");
            listItem.put("desc", "Android机器人");
            listItems.add(listItem);
        }
        return listItems;
    }

    static class ViewHolder{
        public ImageView header;
        public TextView name;
        public TextView desc;
    }


    public class MyAdapter extends BaseAdapter {

        private LayoutInflater mInflater;

        public MyAdapter(Context context){
            this.mInflater = LayoutInflater.from(context);
        }

        @Override
        public int getCount() {
            return 20;
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;

            if (convertView == null){
                holder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.simple_item, null);
                holder.header = (ImageView) convertView.findViewById(R.id.header);
                holder.name = (TextView) convertView.findViewById(R.id.name);
                holder.desc = (TextView) convertView.findViewById(R.id.desc);
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder) convertView.getTag();
            }
            holder.header.setBackgroundResource((Integer) data.get(position).get("header"));
            holder.name.setText((String) data.get(position).get("name"));
            holder.desc.setText((String) data.get(position).get("desc"));
            return convertView;
        }
    }
}

参考书籍博客

《第一行代码》
《Android疯狂讲义》第三版
Android ListView工作原理完全解析,带你从源码的角度彻底理解
android应用开发全程实录-你有多熟悉listview?
android ListView详解
Android杂谈–ListView之BaseAdapter的使用
博客内容是我阅读以上资料加上自己的理解所得,有部分摘抄自以上资料,侵删。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值