zoukankan      html  css  js  c++  java
  • 数据呈现—ListView x Adapter

    无论是在Mobile开发还是桌面开发上,我们都需要显示数据,Android中没有可以直接加载数据的数据网格,任何数据的显示都需要自定义布局。

    其中最常用的两种显示显示数据的控件,一个是ListView,另一个是RecyclerView,他们都需要借助Adapter来动态加载数据,在本节的学习中,我们会讲解如何使用ListView x Adapter的方式加载数据。

    ListView其实只是一个容器,通过Adapter和指定的子项布局来动态的把数据呈现给用户,除了这种方式,ListView还可以直接绑定一个arrays文件用来显示静态数据。

    常见的Adapter对象有:ArrayAdapterSimpleAdapter重写过的BaseAdapter,加上通过绑定arrays文件显示数据,我一共做了四个Demo,让我们来看一下。


    一、ListView x arrays文件

    这种方式很有局限性,只能用来显示静态的文本数据,使用步骤:

    1.在values目录下新建一个arrays.xml文件

    2.编写arrays.xml文件,声明一个string类型的数组标签,并添加三个子项:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string-array name="str_array">
            <item>Value1</item>
            <item>Value2</item>
            <item>Value3</item>
        </string-array>
    </resources>
    

    3.把ListView的entities属性设置为指定数组:

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:entries="@array/str_array"></ListView>
    

    二、ListView x ArrayAdapter文件

    ArrayAdapter是所有Adapter中最简单的一种,因为简单,所以功能也很局限,它只能显示单条文本数据,这点跟静态绑定一样:

    Android代码:

    public class ListViewDemo1Activity extends AppCompatActivity {
    
        List<String> lsData = new ArrayList<>();
        ArrayAdapter<String> arrayAdapter;
        ListView listView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_view_demo1);
    
            lsData.add("张三");
            lsData.add("李四");
            lsData.add("王五");
            arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, lsData);
            listView = findViewById(R.id.lv);
            listView.setAdapter(arrayAdapter);
        }
    }
    

    1.因为ArrayAdapter只能显示文本数据,所以数据源通常是string数组或者列表

    2.实例化ArrayAdapter调用的构造方法中,第一个不用说,是加载列表用的Context对象,传入当前Activity,第二个是布局文件,我们传递一个系统提供的布局文件,该布局文件中只有一个名为text1的TextView,第三项是数据源,用来加载需要绑定的数据,我们传入String集合。

    3.把ArrayAdapter和ListView做绑定


    三、ListView x SimpleAdapter文件

    上面的例子讲了怎么借助ArrayAdapter加载文本列表,但是我们通常要显示的数据肯定不只是一条文本,那怎么显示复杂数据呢?有两种方法,一种是使用SimpleAdapter另一种是使用基于BaseAdapter定制的Adapter,我们先来看第一种:

    子项布局XML代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <ImageView
            android:id="@+id/ivLogo"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_margin="10dp" />
    
        <TextView
            android:id="@+id/tvName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_toRightOf="@id/ivLogo" />
    
        <TextView
            android:id="@+id/tvGender"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/tvName"
            android:layout_margin="10dp"
            android:layout_toRightOf="@+id/ivLogo" />
    </RelativeLayout>
    

    Android代码:

    private List<Map<String, Object>> lsData = new ArrayList<>();
    private SimpleAdapter simpleAdapter;
    private ListView listView;
    private String[] names = {"张三", "李四", "王五"};
    private String[] genders = {"Male", "Female", "Male"};
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view_demo3);
        listView = findViewById(R.id.lv);
        for (int i = 0; i < names.length; i++) {
            Map<String, Object> map_data = new HashMap<>();
            map_data.put("Logo", R.mipmap.ic_launcher);
            map_data.put("Name", names[i]);
            map_data.put("Gender", genders[i]);
            lsData.add(map_data);
        }
        simpleAdapter = new SimpleAdapter(this, lsData, R.layout.simple_item, new String[]{"Logo", "Name", "Gender"}, new int[]{R.id.ivLogo, R.id.tvName, R.id.tvGender});
        listView.setAdapter(simpleAdapter);
    }
    

    1.加载复杂的数据需要先编写一个布局文件,布局文件的代码已经在上面列出来了。

    2.声明一个List<Map<String,Object>>列表,其中String表示Key,Object表示Value

    3.names和genders数组这是为了填充数据而声明的,真实开发中应该是从web/本地数据库上获取数据,在这里我们借用了这连个数组给lsData添加了三条数据,每条数据有三个键值对,分别是Logo、Name、Gender,Logo为了方便,我们都填充了系统一个默认的图标。

    4.实例化SimpleAdapter,第一项不用说,还是Context对象;第二项是子布局文件;第三项是你所有的Key,通过一个数组传入;第四项是一个你每一个Key对应的Value要赋值给子布局中的哪个控件,通过一个int数组传入这些控件的id。

    5.把SimpleAdapter和ListView做绑定


    效果:



    四、ListView x 重写的BaseAdapter文件

    MyAdapter.Java文件:

    public class MyAdapter extends BaseAdapter {
    
        List<Map<String, Object>> lsData;
    
        public ListViewDemo4Adapter(List<Map<String, Object>> lsData) {
            super();
            this.lsData = lsData;
        }
    
        @Override
        public int getCount() {
            return lsData.size();
        }
    
        @Override
        public Object getItem(int position) {
            return lsData.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Map<String, Object> map = lsData.get(position);
            ViewHolder holder;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_item, parent, false);
                holder.ivLogo = convertView.findViewById(R.id.ivLogo);
                holder.tvName = convertView.findViewById(R.id.tvName);
                holder.tvGender = convertView.findViewById(R.id.tvGender);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.ivLogo.setImageResource((Integer) map.get("Logo"));
            holder.tvName.setText(map.get("Name").toString());
            holder.tvGender.setText(map.get("Gender").toString());
            return convertView;
        }
    
        class ViewHolder {
            ImageView ivLogo;
            TextView tvName;
            TextView tvGender;
        }
    }
    

    加载数据的代码:

    private List<Map<String, Object>> lsData = new ArrayList<>();
    private MyAdapter adapter;
    private ListView listView;
    private String[] names = {"A", "B", "C"};
    private String[] genders = {"Male", "Female", "Male"};
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view_demo4);
    
        listView = findViewById(R.id.lv);
        for (int i = 0; i < names.length; i++) {
            Map<String, Object> map_data = new HashMap<>();
            map_data.put("Logo", R.mipmap.ic_launcher);
            map_data.put("Name", names[i]);
            map_data.put("Gender", genders[i]);
            lsData.add(map_data);
        }
        adapter = new MyAdapter(lsData);
        listView.setAdapter(adapter);
    }
    

    1.为了偷懒,布局文件我们还使用之前的布局

    2.编写MyAdapter继承于BaseAdapter,继承之后需要重写一些方法:

    构造方法:传入加载用的数据,通常是个List<Class>对象,为了偷懒,我们没有自己编写类,还是用了上面的List<Map<string,Object>>集合

    getCount():用来获取列表的数量,返回集合的数量即可

    getItem():通过索引获取列表中指定项

    getItemId():本来是获取索引对应的指定项的编号,我们用不着,直接返回索引即可

    getView():核心方法,子项加载的时候调用,列表有多少项,就会加载多少次,用来加载子项要显示的数据,并返回子项,每次上下滑动都会重新加载,为了避免资源浪费,所以我们编写了一个名为ViewHolder的内部类,convertView表示子布局,如果它为空,说明该项还没有别加载过,那就调用LayoutInflater加载该项,并创建一个ViewHolder对象,ViewHolder对象中存储着三个控件的引用,把它们一一和convertView中的控件建立绑定关系,再把它设置为convertView的Tag;如果它不为空,说明已经被加载过了,直接获取它身上的ViewHolder对象即可,无论加载没加载过,调用这个方法的时候都要给控件重新赋值,因为ViewHolder对象中的控件,实际上就是他对应的convertView中的控件的引用(convertView实际上就是一个个子项布局),所以直接给ViewHolder对象中的控件赋值即可,这样也不用再次调用findViewById来获取控件,最后返回convertView即可。

    3.填充List,实例化Adapter,并且绑定给ListView,这样就可以加载数据了。


    效果:

    Everything has its time and that time must be watched. If you have any question, please contact email linqtosql@qq.com.
  • 相关阅读:
    .NET 2.0 WinForm Control DataGridView 编程36计(一)
    Sql Server 日期格式化函数
    FastReport 金额大小写转换自定义函数
    vue.js 三种方式安装(vuecli)
    Android style
    android ui 布局性能优化
    android 手机分辨率
    TCP,IP,HTTP,SOCKET区别和联系
    android2.2 特性
    常见开放api平台OpenAPI
  • 原文地址:https://www.cnblogs.com/Fill/p/10221150.html
Copyright © 2011-2022 走看看