GridView、ListView、Adapter、Map、HashMap
来源:互联网 发布:java中重载的作用 编辑:程序博客网 时间:2024/06/05 16:43
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; @Override protected 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; } //获取数据的长度 @Override public int getCount() { return list.size(); } //获取某一位置的数据 @Override public Object getItem(int position) { return list.get(position); } //用户获取数据的位置 @Override public long getItemId(int position) { return position; } @Override public 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. */ @Override publicvoid 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() { @Override publicvoid 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); } @Override publicint getCount() { return getDate().size();//返回数组的长度 } @Override public Object getItem(int position) { return null; } @Override publiclong getItemId(int position) { return 0; } /**书中详细解释该方法*/ @Override public 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() { @Override publicvoid 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>(); @Override public 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; } @Override public int getCount() { // (在此适配器中所代表的数据集中的条目数) return length; } @Override public Object getItem(int position) { // (获取数据集中与指定索引对应的数据项) return list[position]; } @Override public long getItemId(int position) { // (取在列表中与指定索引对应的行id) return position; } @Override public 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@Overridepublic 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; @Override public 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本身,即this this.mInflater = LayoutInflater.from(context); } @Override public int getCount() { //How many items are in the data set represented by this Adapter. //在此适配器中所代表的数据集中的条目数 return data.size(); } @Override public Object getItem(int position) { // Get the data item associated with the specified position in the data set. //获取数据集中与指定索引对应的数据项 return position; } @Override public long getItemId(int position) { //Get the row id associated with the specified position in the list. //获取在列表中与指定索引对应的行id return position; } //Get a View that displays the data at the specified position in the data set. //获取一个在数据集中指定索引的视图来显示数据 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; //如果缓存convertView为空,则需要创建View if(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里,以便后面方便取出Tag convertView.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; } }}
最后的运行图:
- GridView、ListView、Adapter、Map、HashMap
- ListView GridView Adapter
- ListView GridView - Adapter的优化
- ListView,GridView 和 适配器 Adapter
- ListView、GridView的通用型adapter
- Adapter---打造万能的ListView GridView 适配器
- Adapter---打造万能的ListView GridView 适配器
- Android打造万能的ListView GridView Adapter
- 打造通用Adapter(适用于ListView,GridView)
- 自定义通用Adapter适配ListView GridView
- Android ListView,GridView的Adapter封装
- 通用型的listview/gridview适配器adapter
- 自定义通用Adapter适配ListView GridView
- ListView和GridView的adapter的抽取
- ListView、GridView的adapter一笔带过【LGBaseAdapter】
- 封装一个通用的 listview/gridview Adapter
- ListView,GridView的Adapter中的getView执行异常
- ListView,GridView,Gallery的Adapter中的getView多次调
- Mybatis入门示例(一):基础代码
- Error: L6218E: Undefined symbol (referred from main.o)
- Python中的map_reduce
- 架构的启蒙
- python os模块常用函数
- GridView、ListView、Adapter、Map、HashMap
- PAT-A1023. Have Fun with Numbers (20)
- zjnuSAVEZ (字符串hash)
- JUnit运行流程
- uploadity实现文件上传(获取文件路径,进度,)
- PAT-A1024. Palindromic Number (25)
- Session 和 Cookie 的知识
- [土狗之路]coursera C语言进阶 习题 含k个3的数
- FZU 1106 Sum of Factorials