一、概述
AdapterView不仅仅是UI,同时还将数据关联到UI上,例如在手机中经常使用的ListView就是AdapterView。
他的实现过程就类似于MVC框架(MVC框架,实现原理:数据模型M(Model)存放数据,处理业务逻辑,利用控制器C(Controller)将数据显示在视图V(View)上。)。他的使用不像其他控件一样,拖拽到界面上就能用,而是需要通过适配器将某些样式的数据或控件添加到其上而使用。
(1)将前端显示和后端数据分离
(2)内容不能通过ListView.add的形式添加列表项,需指定一个Adapter对象,通过它获得显示数据
(3)ListView相当于MVC框架中的V(视图)
(4)Adapter相当于MVC框架中的C(控制器)
(5)数据源相当于MVC框架中的M(模型)
(6)超出屏幕显示之后,自动加上滚动条
二、AdapterView
AdapterView继承了ViewGroup,它的本质是容器
AdapterView 可以包含多个 “列表项”,并将多个“列表项”以合适的形式显示出来
AdapterView显示的多个“列表项”由Adapter提供
分类
(1)ListView:列表
(2)Spinner:下拉列表,给用户提供选择
(3)Gallery:缩略图,已经被水平的ScrollView和ViewPicker取代,但也还算常用,是一个可以把子项以中心锁定,水平滚动的列表
(4)GridView:网格图,以表格形式显示资源,可以左右滑动的
ScrollView 如果一个页面内容以及超出了屏幕,可以使用ScrollView,里面只能放一个布局或者控件
事件
(1)用户单击列表项事件
◆为列表加载setOnItemClieckListener监听,重写onItemClick(发生单击事件的列表对象ListView,被单击控件对象view,
在列表中的位置position,被单击列表项的行ID)方法。
(2)用户长按事件
◆为列表加载setOnItemLongClieckListener监听,重写onItemLongClick(发生单击事件的列表对象ListView,被单击控件对象view,
在列表中的位置position,被单击列表项的行ID)方法。
三、Adapter(C)
把数据源中数据以某种样式(xml文件)显示在视图中。
Adapter的类关系图
分类
Adapter常用的实现类
1、ArrrayAdapter:简单、易用,通常用于数组或List集合的多个值包装成多个列表项
2、SimpleAdapter:功能有点强,可用于将List集合的多个对象包装成多个列表项
3、SimpleCursorAdapter:与SimpleAdapter基本相似,只是用于包装Cursor提供的数据
4、BaseAdapter:通常用于被扩展。扩展BaseAdapter可以对各列表项进行最大限度的定制
实现BaseAdapter
扩展BaseAdapter可以取得对Adapter最大的控制权:程序要创建多少个列表项,每个列表项的组件都由开发者来决定。
比较*
扩展该对象需要重写如下4个方法:
1、getCount():该方法的返回控制该Adapter将会包含多少个列表项
2、getItem(int position):该方法的返回值决定第position处的列表项的内容
3、getItemId(int position):该方法的返回值决定第position处的列表项的ID
4、getView(it position,View convertView,viewGroup parent):该方法的返回值决定第position处的列表项组件
//数组适配器ArrayAdapter
1、先获得一个ListView 对象 布局里面写一个ListView控件,Activity里面findViewById返回一个ListView对象
2、获得一个数组或者集合的数据类型,元素为单一的数据
3、适配器:子item布局、布局里面控件的ID
//例子
ListView 与ArrayAdapter
private ListView lv;
String[] datas = {"Android","Ios","Java","Php",".Net"};
lv = (ListView) findViewById(R.id.lv);
//数组适配器 朱能放一个数据
//参数1 上下文对象
//参数2 布局
//参数3 控件ID
//参数4 数据源 数组 集合
// ArrayAdapter<String> adapter = new ArrayAdapter<String>
// (this, R.layout.lv_textview, R.id.tv, datas);
//布局也可以使用系统自带
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.activity_list_item, android.R.id.text1, datas);
//关联adapterView和Adater
lv.setAdapter(adapter);
AdapterView的属性
listView的属性
适配器更新数据
加载数据在子线程(主线程不能经历耗时操作)
原因
//View只能在主线程中刷新和绘制
Handler 线程与线程之间的通信
Handler handler = new Handler(){
//handler接收子线程发送的消息
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("msg", "handler调用");
switch (msg.what) {
case 0:
adapter.notifyDataSetChanged();//刷新适配器
break;
default:
break;
}
}
};
class MyThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("C++");
handler.sendEmptyMessage(0);//handler发送一个消息
}
}
//SimpleApadter
package com.bwf.a18_adapterview;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class SimpleAdapterActivity extends Activity{
private ListView lv = null;
private SimpleAdapter adapter;
//数据源
private List<Map<String, Object>> datas = new ArrayList<Map<String,Object>>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
// lv = (ListView)findViewById(R.id.lv);
lv = (ListView) findViewById(R.id.lv);
//获得数据源
//第一列
Map<String , Object> map1 = new HashMap<String, Object>();
map1.put("project", "Android");
map1.put("score", "100");
map1.put("img", R.drawable.iamge1);
//第二列
Map<String , Object> map2 = new HashMap<String, Object>();
map2.put("project", "Java");
map2.put("score", "70");
map2.put("img", R.drawable.image2);
//第三列
Map<String , Object> map3 = new HashMap<String, Object>();
map3.put("project", "C++");
map3.put("score", "90");
map3.put("img", R.drawable.image3);
//第四列
Map<String , Object> map4 = new HashMap<String, Object>();
map4.put("project", "PHP");
map4.put("score", "69");
map4.put("img", R.drawable.iamge4);
//把每列数据添加到数据源的集合中
datas.add(map1);
datas.add(map2);
datas.add(map3);
datas.add(map4);
//简单适配器
//1 上下文对象
//2 数据源
//3 item的layout
//4 字符串数组 map 的key
//5 整数数组 控件id
adapter = new SimpleAdapter(this, datas, R.layout.simple_item,
new String[]{"img" , "project" , "score"}, new int[]{R.id.simple_img,R.id.simple_tv,R.id.simple_btn});
lv.setAdapter(adapter);//绑定适配器
//设置每个item的监听
lv.setOnItemClickListener(new OnItemClickListener() {
//position 点击的item位置 从0开始
//view 每个item的view对象
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//获得Item的每个子View
TextView tv = (TextView) view.findViewById(R.id.simple_tv);
// TextView tv = (TextView) view.getChildAt(1);
Log.i("msg", tv.getText().toString());
}
});
}
}
08-30 16:38:57.548: E/AndroidRuntime(25872): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
只有主线程可以创建一个view和修改一个view
总结:
1、AdapterView与Adapter的组成,原理
MVC: V:ListView C: Adapter M:模型 数据源 业务逻辑和数据处理
2、ArrayAdapter+ListView
1、特点:只能放一个TextView的内容
2、可以使用系统自带的布局
3、ListView的属性和方法
4、SimpleAapter+ListView
1、可以放多个控件(CheckBOx、TextView、ImageView)
5、Handler 做线程之间的通信
6、Adapter刷新数据notifyDataSetChanged 必须在主线程中刷新View