声明:刚开始学习Android技术,笔记中可能会有一些错误,如有发现请下方评论指出
Adapter应该是安卓中比较重要的一个知识点,官方文档说Adapter扮演一个在AdapterView即视图和底层数据之间桥梁,Adapter提供对每个数据项的访问,并且为数据集建立视图访问。简单来说就是适配器Adapter给我们的界面提供数据,给用户看。主要有三种Adapter:(可以把Adapter翻译为适配器)
一. ArrayAdapter的使用
ArrayAdapter使用相对简单,但是功能也很局限,基本上只能显示一行的文本,基本使用如下:
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
ListView>
public class MainActivity extends AppCompatActivity {
private ListView mListView;
private String[] dateTest={"vivo","xiaomi","oppo","huawei","vivo","xiaomi","oppo","huawei"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.list_view);
ArrayAdapter<String> myAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,dateTest);
mListView.setAdapter(myAdapter);
mListView.setOnItemClickListener(mMessageOnclick);
}
private AdapterView.OnItemClickListener mMessageOnclick = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Toast.makeText(MainActivity.this,"click"+position,Toast.LENGTH_SHORT).show();
}
};
}
ArrayAdapter myAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,dateTest);参数说明
最终结果如下:
二. SimpleAdapter
这个适配器使用起来还是比较方便的,使用方法没有BaseAdapter那么复杂,但是却可以很方便地实现一些复杂地Item,下面是一个使用方法:
activity_main.xml中添加ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
ListView>
LinearLayout>
创建一个布局my_item_view,用来显示一个稍复杂的列表项;其实就是应用商店一个应用的下载列表布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="80dp">
<ImageView
android:id="@+id/app_img"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center"
android:src="@drawable/wangzhe"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_weight="3"
android:layout_height="match_parent">
<TextView
android:id="@+id/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_app_name"
android:layout_margin="5dp"
android:textSize="20sp"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/app_kind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="Social"/>
<TextView
android:id="@+id/app_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="100MB"/>
LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/app_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="4.6分"
android:textColor="@color/colorScore"
/>
<TextView
android:id="@+id/app_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:text="106Million"/>
LinearLayout>
LinearLayout>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp"
android:layout_gravity="center"
android:text="@string/title_button"
android:layout_marginHorizontal="10dp"/>
LinearLayout>
在MainActivity.java中给列表添加适配器,装载数据;数据先使用的假数据
public class MainActivity extends AppCompatActivity {
private List<Map<String,Object>> mDataTest;
private ListView mListView;
private SimpleAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.list_view);
initDate();
mAdapter = new SimpleAdapter(MainActivity.this,mDataTest,R.layout.item_list,
new String[]{"gameName","gameVolume","gameImg"},new int[]{R.id.app_name,R.id.app_volume,R.id.app_img});
mListView.setAdapter(mAdapter);
}
private void initDate(){
//这里先只添加这三个值,实际中这些值都是要从服务器获取
String[] gameName = {"王者荣耀","绝地求生","穿越火线"};
String[] gameVolume = {"1432MB","1230MB","1110MB"};
int[] gameImg ={R.drawable.wangzhe,R.drawable.chiji,R.drawable.chuanyue};
mDataTest = new ArrayList<>();
for(int i = 0;i<gameName.length;i++){
Map<String,Object> map = new HashMap<>();
map.put("gameName",gameName[i]);
map.put("gameVolume",gameVolume[i]);
map.put("gameImg",gameImg[i]);
mDataTest.add(map);
}
}
}
这里的重点是SimpleAdapter的5个参数,比ArrayAdapter参数复杂,功能也更加强大
第二个第四个第五个参数其实都是对应的。只要将数据处理成相应的格式,使用SimpleAdapter还是很方便的
最终结果如下:
三. BaseAdapter
BaseAdapter是适配器通用的基类,使用相对复杂,功能也更加强大;使用的思想其实是差不多的,但是可能面对大量数据性能会不同吧。
activity.xml和列表项item的布局与第二个SimpleAdapter相同
新建一个数据结构的类AppMessage用来存放我们的数据
public class AppMessage {
private int imgId;
private String appName;
private String appVolume;
private String appScore;
private String appDownload;
public AppMessage(int imgId, String appName, String appVolume, String appScore, String appDownload) {
this.imgId = imgId;
this.appName = appName;
this.appVolume = appVolume;
this.appScore = appScore;
this.appDownload = appDownload;
}
public int getImgId() {
return imgId;
}
public String getAppName() {
return appName;
}
public String getAppVolume() {
return appVolume;
}
public String getAppScore() {
return appScore;
}
public String getAppDownload() {
return appDownload;
}
}
新建一个MyAdapter类继承自BaseAdapter
public class MyAdapter extends BaseAdapter {
private List<AppMessage> mData;
private Context mContext;
//构造函数初始化数据和上下文
public MyAdapter(List<AppMessage> data, Context context) {
this.mData = data;
this.mContext = context;
}
//列表项的数量
@Override
public int getCount() {
return mData.size();
}
//获取某一个列表项
@Override
public Object getItem(int i) {
return mData.get(i);
}
//获取列表项位置
@Override
public long getItemId(int i) {
return i;
}
//设置列表项的的布局,并且插入相应数据
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = LayoutInflater.from(mContext).inflate(R.layout.item_list, viewGroup, false);
ImageView appImg = (ImageView) view.findViewById(R.id.app_img);
TextView appVolume = (TextView) view.findViewById(R.id.app_volume);
TextView appName = (TextView) view.findViewById(R.id.app_name);
TextView appScore = (TextView) view.findViewById(R.id.app_score);
TextView appDownload = (TextView) view.findViewById(R.id.app_download);
appImg.setImageResource(mData.get(i).getImgId());
appDownload.setText(mData.get(i).getAppDownload());
appName.setText(mData.get(i).getAppName());
appScore.setText(mData.get(i).getAppScore());
appVolume.setText(mData.get(i).getAppVolume());
return view;
}
}
这个适配器需要重写4个函数,几个函数的作用显而易见,除此之外需要创建一个构造函数来初始化数据结构和上下文context,主要部分是getView()函数,获取到我们的列表项视图,然后将数据填充到其中,但是上面这种做法Google官方是不推荐的,会有如下提示:
官方推荐我们使用ViewHolder,应该是处于效率的考虑。可以看到上述代码中的getView()函数的执行次数应该是数据项的个数,那么当数据量大时每加载一个数据项就要创建一次view视图,就要执行多次findViewById,这样效率的相对较低的,所以可以使用另一种写法。实现出来的效果如下:
public class MyAdapter extends BaseAdapter {
private List<AppMessage> mData;
private Context mContext;
//构造函数初始化数据和上下文
MyAdapter(List<AppMessage> data, Context context) {
this.mData = data;
this.mContext = context;
}
//列表项的数量
@Override
public int getCount() {
return mData.size();
}
//获取某一个列表项
@Override
public Object getItem(int i) {
return mData.get(i);
}
//获取列表项位置
@Override
public long getItemId(int i) {
return i;
}
//第二种相对高效的写法,不用每次都创建View对象和findViewById
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if (view == null) { //如果没有view视图,则创建一个
viewHolder = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.item_list, viewGroup, false);
viewHolder.appImg = (ImageView) view.findViewById(R.id.app_img);
viewHolder.appVolume = (TextView) view.findViewById(R.id.app_volume);
viewHolder.appName = (TextView) view.findViewById(R.id.app_name);
viewHolder.appScore = (TextView) view.findViewById(R.id.app_score);
viewHolder.appDownload = (TextView) view.findViewById(R.id.app_download);
view.setTag(viewHolder); //设置与view视图关联的标记
} else { //除第一个item后其他的都是else,只需要获取之前标记的viewHolder就行
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.appImg.setImageResource(mData.get(i).getImgId());
viewHolder.appDownload.setText(mData.get(i).getAppDownload());
viewHolder.appName.setText(mData.get(i).getAppName());
viewHolder.appScore.setText(mData.get(i).getAppScore());
viewHolder.appVolume.setText(mData.get(i).getAppVolume());
return view;
}
private class ViewHolder {
private ImageView appImg;
private TextView appVolume;
private TextView appName;
private TextView appScore;
private TextView appDownload;
}
}
这种写法if中的代码只需要执行一次,会提升一定的效率。
除以上之外还有recycleView实现滑动列表,它的适配器需要继承RecycleView.Adapter回头整理