GridView、ListView、Adapter、Map、HashMap

article/2025/9/10 8:38:09

1.ListView自定义适配器adapter
注:Android适配器是数据和视图之间的桥梁,以便于数据在View上显示。适配器就像显示器,把复杂的东西按人可以接受的方式来展现。
(1)首先将适配器的View视图表现出来,使用ListView为例:

<?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="vertical"><ListView
        android:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></LinearLayout>

(2)把调用适配器的代码写好,之后再自定义适配器。

public class MainActivity extends AppCompatActivity {private ListView listView;private MyAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.adapter);listView = (ListView) findViewById(R.id.listview);adapter = new MyAdapter(getData());listView.setAdapter(adapter);}
}

(3)现在开始自定义适配器,名字命名为MyAdapter,继承BaseAdapter,并重载这个抽象类的方法,实现其功能:

public class MyAdapter extends BaseAdapter{private List<String> list;//构造函数使其属性本地化,方便加载数据public MyAdapter(List<String> list){this.list = list;}//获取数据的长度@Overridepublic int getCount() {return list.size();}//获取某一位置的数据@Overridepublic Object getItem(int position) {return list.get(position);}//用户获取数据的位置@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {TextView textView = new TextView(MainActivity.this);textView.setText(list.get(position));return textView;}}

(4)因为自定义适配器中用到了List集合,所以新建立一个getData方法,用于获取和存储数据。然后就可以通过适配器按照我们自定义的形式展示出来。

public List<String> getData(){List<String> list = new ArrayList<String>();for (int i = 0; i<10;i++){list.add("xyy"+i);}return list;}

2.使用BaseAdapter优化ListView
注:(1)其中BaseAdapter需要重写的方法:getCount(),getItem(int position),getItemId(int position),getView(int position, View convertView, ViewGroup parent)listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到 listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。

当手动完成适配时,必须手动映射数据,这需要重写getView()方 法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文 件中inflate来的布局。我们用LayoutInflater的方法将定义好的item.xml文件提取成View实例用来显示。然后将xml文件中 的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。

现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要 绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个 ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那再绘制下一行,直到绘完为止。
(2)在实际开发中LayoutInflater这个类的作用类似findViewById()。不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入。

代码实例:

publicclass MyListViewBase extends Activity {private ListView lv;//定义一个动态数组    ArrayList<HashMap<String, Object>>listItem;/** Called when the activity is first created. */@Overridepublicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);lv = (ListView) findViewById(R.id.lv);MyAdapter mAdapter = new MyAdapter(this);//得到一个MyAdapter对象lv.setAdapter(mAdapter);//为ListView绑定Adapter/**为ListView添加点击事件*/lv.setOnItemClickListener(new OnItemClickListener() {@Overridepublicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {Log.v("MyListViewBase", "你点击了ListView条目" + arg2);//在LogCat中输出信息                }});}/**添加一个得到数据的方法,方便使用*/private ArrayList<HashMap<String, Object>> getDate(){ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,Object>>();/**为动态数组添加数据*/    for(int i=0;i<30;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("ItemTitle", "第"+i+"行"); map.put("ItemText", "这是第"+i+"行"); listItem.add(map); }return listItem;}/** 新建一个类继承BaseAdapter,实现视图与数据的绑定*/privateclass MyAdapter extends BaseAdapter {private LayoutInflater mInflater;//得到一个LayoutInfalter对象用来导入布局 /**构造函数*/public MyAdapter(Context context) {this.mInflater = LayoutInflater.from(context);}@Overridepublicint getCount() {return getDate().size();//返回数组的长度        }@Overridepublic Object getItem(int position) {return null;}@Overridepubliclong getItemId(int position) {return 0;}/**书中详细解释该方法*/        @Overridepublic View getView(finalint position, View convertView, ViewGroup parent) {ViewHolder holder;//观察convertView随ListView滚动情况            Log.v("MyListViewBase", "getView " + position + " " + convertView);if (convertView == null) {convertView = mInflater.inflate(R.layout.item,null);holder = new ViewHolder();/**得到各个控件的对象*/                    holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);holder.text = (TextView) convertView.findViewById(R.id.ItemText);holder.bt = (Button) convertView.findViewById(R.id.ItemButton);convertView.setTag(holder);//绑定ViewHolder对象                   }else{holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象                  }/**设置TextView显示的内容,即我们存放在动态数组中的数据*/            holder.title.setText(getDate().get(position).get("ItemTitle").toString());holder.text.setText(getDate().get(position).get("ItemText").toString());/**为Button添加点击事件*/             holder.bt.setOnClickListener(new OnClickListener() {@Overridepublicvoid onClick(View v) {Log.v("MyListViewBase", "你点击了按钮" + position);//打印Button的点击信息                    }});return convertView;}}/**存放控件*/publicfinal class ViewHolder{public TextView title;public TextView text;public Button   bt;}
}

3.ArrayList和ListView:
列表的显示需要三个元素:
1.ListVeiw 用来展示列表的View。
2.适配器 用来把数据映射到ListView上的中介。
3.数据 具体的将被映射的字符串,图片,或者基本组件。
其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方便的把数据库的内容以列表的形式展示出来。

public class MyListView extends Activity {private ListView listView;//private List<String> data = new ArrayList<String>();@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);listView = new ListView(this);listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));setContentView(listView);}private List<String> getData(){List<String> data = new ArrayList<String>();data.add("测试数据1");data.add("测试数据2");data.add("测试数据3");data.add("测试数据4");return data;}
}

注:上面代码使用了ArrayAdapter(Context context, int textViewResourceId, List objects)来装配数据,要装配这些数据就需要一个连接ListView视图对象和数组数据的适配器来两者的适配工作,ArrayAdapter的构造需要三个参数,依次为this,布局文件(注意这里的布局文件描述的是列表的每一行的布局android.R.layout.simple_list_item_1是系统定义好的布局文件只显示一行文字,数据源(一个List集合)。同时用setAdapter()完成适配的最后工作。
运行后的现实结构如下图:
这里写图片描述

4.ListView之BaseAdapter的基本使用及两种优化模式:
BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置,比如:

SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info"},new int[]{R.id.img, R.id.title, R.id.info});

但是在BaseAdapter中需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如:

class MyAdapter extends BaseAdapter{private Context context;public MyAdapter(Context context){this.context = context;}@Overridepublic int getCount() {// (在此适配器中所代表的数据集中的条目数)return length;}@Overridepublic Object getItem(int position) {// (获取数据集中与指定索引对应的数据项)return list[position];}@Overridepublic long getItemId(int position) {// (取在列表中与指定索引对应的行id)return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// Get a View that displays the data at the specified position in the data set.return null;}}

getView处理方式:
第一种方法:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式。

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;}

第二种方法:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能。

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;}

第三种方法:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。
注:当我们判断 convertView == null 的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)
如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。

//在外面先定义,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;
}

ViewHolder类的作用:
ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById()。
实例:用BaseAdapter来自定义ListView布局:
main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><ListView
        android:id="@+id/lv"android:layout_width="fill_parent"android:layout_height="wrap_content"android:fastScrollEnabled="true"/>
</LinearLayout>

list_item.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" ><ImageView
        android:id="@+id/img"android:layout_width="wrap_content"android:layout_height="wrap_content"/><LinearLayout
        android:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextView
            android:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="20sp"/><TextView
            android:id="@+id/info"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="14sp"/></LinearLayout></LinearLayout>

Activity

package com.loulijun.demo17;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class Demo17Activity extends Activity {private ListView lv;private List<Map<String, Object>> data;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);lv = (ListView)findViewById(R.id.lv);//获取将要绑定的数据设置到data中data = getData();MyAdapter adapter = new MyAdapter(this);lv.setAdapter(adapter);}private List<Map<String, Object>> getData(){List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();Map<String, Object> map;for(int i=0;i<10;i++){map = new HashMap<String, Object>();map.put("img", R.drawable.ic_launcher);map.put("title", "跆拳道");map.put("info", "快乐源于生活...");list.add(map);}return list;}//ViewHolder静态类static class ViewHolder{public ImageView img;public TextView title;public TextView info;}public class MyAdapter extends BaseAdapter{   private LayoutInflater mInflater = null;private MyAdapter(Context context){//根据context上下文加载布局,这里的是Demo17Activity本身,即thisthis.mInflater = LayoutInflater.from(context);}@Overridepublic int getCount() {//How many items are in the data set represented by this Adapter.//在此适配器中所代表的数据集中的条目数return data.size();}@Overridepublic Object getItem(int position) {// Get the data item associated with the specified position in the data set.//获取数据集中与指定索引对应的数据项return position;}@Overridepublic long getItemId(int position) {//Get the row id associated with the specified position in the list.//获取在列表中与指定索引对应的行idreturn position;}//Get a View that displays the data at the specified position in the data set.//获取一个在数据集中指定索引的视图来显示数据@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;//如果缓存convertView为空,则需要创建Viewif(convertView == null){holder = new ViewHolder();//根据自定义的Item布局加载布局convertView = mInflater.inflate(R.layout.list_item, null);holder.img = (ImageView)convertView.findViewById(R.id.img);holder.title = (TextView)convertView.findViewById(R.id.tv);holder.info = (TextView)convertView.findViewById(R.id.info);//将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出TagconvertView.setTag(holder);}else{holder = (ViewHolder)convertView.getTag();}holder.img.setBackgroundResource((Integer)data.get(position).get("img"));holder.title.setText((String)data.get(position).get("title"));holder.info.setText((String)data.get(position).get("info"));return convertView;}}
}

最后的运行图:
这里写图片描述


http://chatgpt.dhexx.cn/article/QCqW0jwj.shtml

相关文章

GridViewPager

GridViewPager ViewPager结合GridView&#xff0c;轻松实现类似表情面板的控件。可自由定制Item布局&#xff0c;提供充足的自定义参数等。也处理了条目点击事件和条目长按事件。效果如下&#xff1a; Demo下载地址&#xff1a;GridViewPager &#xff0c;或者扫描以下二维码…

libevent 编译

1.下载源码 github:https://github.com/libevent/libevent 官网&#xff1a;http://libevent.org/ 2.CMake 编译 在libevent源码目录建立文件夹&#xff1a;BuildVs2010_x64 2.打开CMake 3.BuildVs2010_x64 下此时生成了vs2010的解决方案。然后编译生成就ok NOTE&#x…

13、《Libevent中文帮助文档》学习笔记13:Linux下集成、运行libevent

Linux下编译libevent的指导可以参考《4、《Libevent中文帮助文档》学习笔记4&#xff1a;Linux下编译libevent》&#xff0c;完成编译、安装&#xff0c;生成so库后&#xff0c;其他程序即可依赖libevent的so库&#xff0c;使用libevent的功能。 由于没有通过prefix指定安装路…

libevent 编译与安装 (WIN10 visual studio2019, ubuntu,centos)

文章目录 一、准备安装包二、编译与安装编译zlib编译openssl编译libevent 三、libevent集成zlib测试程序修改编译&#xff08;可选&#xff09;四、测试程序五、linux(ubuntu)测试安装依赖环境&#xff0c;依次编译zlib,openssl,libeventwindows与linux共享文件夹&#xff08;使…

Libevent 学习一:Libevent 源码编译

文章目录 Libevent 学习一&#xff1a;Libevent 源码编译Libevent Windows 编译Windows 编译环境安装 Visual Studio Community 2015安装 zlib安装 OpenSSL安装 Libeventcmake 安装 LibeventLibevent 测试程序 Libevent Linux编译CentOS 7 安装 LibeventLibevent 测试程序 Libe…

libevent mysql_libevent安装总结

1.先用&#xff1a;ls -al /usr/lib | grep libevent 查看是否已安装&#xff1b;如果已安装且版本低于1.3&#xff0c;则先通过&#xff1a;rpm -e libevent —nodeps进行卸载。 2.下载libevent安装包&#xff1a;libevent-2.0.18-stable.tar.gz。 wget https://github.com/do…

在window用vcpkg安装libevent

参考readme https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md 使用的PackageManager方式安装&#xff0c; Package Managers 下载 vcpkg 依赖管理包 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.bat ./vcpkg integrate…

libevent实践01:准备源码、搭建项目、编译脚本和入门例子

编译源码 libevent是一个Reactor事件库。 我的理解&#xff0c;就是封装了select、epoll、poll的函数库。有使用select&#xff0c;poll&#xff0c;epoll的需求就可以使用的。 官网地址&#xff1a;https://libevent.org/ 下载源码&#xff1a; https://github.com/libev…

libevent(1)windows下安装libevent

Socket通信库libevent成熟、稳定、性能高&#xff0c;在unix和windows下都能使用&#xff0c;在证券交易领域也有不少成功的应用&#xff0c;已经用事实证明是非常棒的socket通信库。对我们目前交易系统的unix重构来说&#xff0c;是比较合适的选择 –– 坑少、在证券交易项目中…

Libevent库的学习

目录 Libevent 概述 Libevent 使用模型 使用Libevent的基本流程&#xff1a; libevent 的核心&#xff0c;event 事件 1. 创建一个事件event 2. 释放event_free 3. 注册event 4. 信号事件 5. 销毁event_base Libevent 结构图 使用libevent库去实现tcp服务器 Libev…

编译libevent

本文记录在win10编译libevent的过程 1.编译前准备zlib,openssl zlib网址 http://www.zlib.net/ 下载源码解压缩 打开vs的dos窗口 32位选择32位窗口这里选择64位,cd 到解压后的文件夹 执行 nmake /f win32/Makefile.msc 执行后可以看到目录下有lib文件和dll文件和测试文件…

libevent简要介绍

libevent库 开源。精简。跨平台&#xff08;Windows、Linux、Maxos、unix&#xff09;。专注于网络通信。 源码包安装&#xff1a; ./configure 检查安装环境 生成makefile make 生成.o和可执行文件 sudo make install …

Libevent库的简介

一、libevent是什么 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b…

libevent库学习(1)

一、初识 1、libevent介绍 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&…

详解Libevent网络库

项目中要用到libevent&#xff0c;所以就自学了libevent&#xff0c;参考资料为张亮的《libevent源码深度剖析》和《linux高性能服务器编程》 Libevent简介 Libevent是开源社区一款高性能的I/O框架库&#xff0c;其具有如下特点&#xff1a; 1.跨平台支持。Libevent支持Linu…

Libevent库的介绍与应用

Libevent库 Libevent概述Libevent使用模型Libevent库使用示例Libevent事件类型和框架结构使用Libevent完成tcp服务端 Libevent概述 Libevent是开源社区的一款高性能的I/O框架库&#xff0c;使用Libevent的著名案例有&#xff1a;高性能的分布式内存对象缓存软件memcached,Goog…

Linux c 开发 - libevent

目录 一、event_base 1. 创建event_base 2. 查看IO模型 3. 销毁event_base 4. 事件循环 event loop 5. event_base的例子 二、event 事件 1. 创建一个事件event 2. 释放event_free 3. 注册event 4.event_assign 5. 信号事件 6. event细节 三、Socket实例 四、Bu…

安装svn客户端

下载地址 下载 TortoiseSVN 我的网盘地址&#xff1a; 百度网盘 请输入提取码 提取码&#xff1a; em9s 1、安装客户端 双击运行&#xff1a; 点击【next】 点击【next】 选择好路径后&#xff0c;点击【next】 点击【install】安装 点击【finish】完成安装。安装完成后重…

SVN客户端配置--客户端

一、使用客户端软件连接SVN服务器 在项目文件夹中单击右键–>TortoiseSVN–>Repo-browser,并在弹出框中贴入URL&#xff08;svn://服务器IP&#xff09; 在图中指定的位置单击右键选择checkput 点击OK点击OK SVN的三大指令 指令名称Checkout①连接到SVN服务器②更新服务…

SVN客户端(TortoiseSVN)安装及使用说明

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; SVN客户端(TortoiseSVN)安装及使用说明 ⏱️ 创作时间&#xff1a; 20…