Android Adapter相关学习及使用方法

声明:刚开始学习Android技术,笔记中可能会有一些错误,如有发现请下方评论指出

Adapter应该是安卓中比较重要的一个知识点,官方文档说Adapter扮演一个在AdapterView即视图和底层数据之间桥梁,Adapter提供对每个数据项的访问,并且为数据集建立视图访问。简单来说就是适配器Adapter给我们的界面提供数据,给用户看。主要有三种Adapter:(可以把Adapter翻译为适配器)

  • BaseAdapter
  • ArrayAdapter
  • CurosrAdapter
  • SimpleCursorAdapter

一. ArrayAdapter的使用

​ ArrayAdapter使用相对简单,但是功能也很局限,基本上只能显示一行的文本,基本使用如下:

  1. 布局文件:activity_main.xml
<ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
</ListView>
  1. Java文件:MainActivity.java
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();
        }
    };
}
  1. ArrayAdapter myAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,dateTest);参数说明

    • 第一个参数:Context上下文
    • 第二个参数:每一个Item的样式,Android Studio会提示使用,有很多种;也可以直接使用R.layout.diy_item.xml自定义item布局
    • 第三个参数:数据源,是一个数组或者集合数组
  2. 最终结果如下:

    在这里插入图片描述


二. SimpleAdapter

​ 这个适配器使用起来还是比较方便的,使用方法没有BaseAdapter那么复杂,但是却可以很方便地实现一些复杂地Item,下面是一个使用方法:

  1. activity_main.xml中添加ListView

    <?xml version="1.0" encoding="utf-8"?>
    <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>
    
  2. 创建一个布局my_item_view,用来显示一个稍复杂的列表项;其实就是应用商店一个应用的下载列表布局:

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<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>

  1. 在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);
            }
    
        }
    }
    
    
  2. 这里的重点是SimpleAdapter的5个参数,比ArrayAdapter参数复杂,功能也更加强大

    • 第一个参数:上下文Context
    • 第二个参数:一个包含Map类型的List集合,就是我们需要显示出来的数据,以键值对的形式给出
    • 第三个参数:列表项Item的布局
    • 第四个参数:数据来源,String数组中的每一个元素与第二个参数中的Map类型的key相对应
    • 第五个参数:数据去向,int数组中为item布局中每一个组件的id,就是第三个布局文件中的id。是将第四个参数中的数据填充到对应的显示组件中

    第二个第四个第五个参数其实都是对应的。只要将数据处理成相应的格式,使用SimpleAdapter还是很方便的

  3. 最终结果如下:

    在这里插入图片描述


三. BaseAdapter

​ BaseAdapter是适配器通用的基类,使用相对复杂,功能也更加强大;使用的思想其实是差不多的,但是可能面对大量数据性能会不同吧。

  1. activity.xml和列表项item的布局与第二个SimpleAdapter相同

  2. 新建一个数据结构的类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;
        }
    }
    
    
  3. 新建一个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回头整理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值