什么是数据适配器?

下图展示了数据源、适配器、ListView等数据展示控件之间的关系。我们知道,数据源是各种各样的,而ListView所展示数据的格式则是有一定的要求的。数据适配器正是建立了数据源与ListView之间的适配关系,将数据源转换为ListView能够显示的数据格式,从而将数据的来源与数据的显示进行解耦,降低程序的耦合性。这也体现了Android的适配器模式的使用。对于ListView、GridView等数据展示控件有多种数据适配器,本文讲解最通用的数据适配器——BaseAdapter。

Android-0.数据适配器BaseAdapter接口简介

Recycler缓存机制

这些适配器使用相同组件动态绑定数据的方式进行优化。为什么需要优化呢?因为如果我们有大量的数据要显示怎么办?为每个数据创建一个新视图?这不可能,因为内存有限制。实际上Android为你缓存了视图。Android中有个叫做Recycler的构件,下图是它的工作原理:

Android-0.数据适配器BaseAdapter接口简介
Recyler可以理解为一个队列,用来存储不在屏幕范围内的item,如果item滚出屏幕范围,那么就入队,这里的滚出是完全滚出,即边界等也要完全滚出。如果新的item要滚进来,那么android系统的framework就会查看Recyler是否含有可以重复使用的View,如果有那么就重新设置该View 的数据源,然后显示,即出队。大小一般为手机屏幕所包含的item的个数,再加上2

接口函数

 public int getCount()
 public Object getItem(int position)
 public long getItemId(int position) 
 public View getView(int position, View convertView, ViewGroup parent)

简略流程图:

Android-0.数据适配器BaseAdapter接口简介
以下分次介绍各函数:
 public int getCount()

获取我们将要绘制的item数目,这个数目不能大于总item数目,但可以小于总item数目。例如我们adapter管理的item总数有10个,而我们通过getCount()返回的只有6个,那么最终GridView绘制出来的将只有6个。

 public Object getItem(int position)

getItem方法不是在Baseadapter类中被调用的,而是在Adapterview.getItemAtPosition(position) 中被调用的。
getItemAtPosition(position) 是在setOnItemClickListenersetOnItemLongClickListenersetOnItemSelectedListener的点击选择处理事件中方便地调用来获取当前行数据的。

public long getItemId(int position) 

该方法的返回值决定第position处的列表项的ID,某些方法有id这个参数,而这个id参数就是取决于getItemId()这个返回值,如:

 mRecordLed.setOnItemClickListener(new AdapterView.OnItemClickListener() {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {}
  });


 public View getView(int position, View convertView, ViewGroup parent)

通过传入的参数position,加工成我们想要的View并返回,最终供GridView使用。
position是指当前dataset的位置,通过getCountgetItem来使用。如果list向下滑动的话那么就是最低端的item的位置,如果是向上滑动的话那就是最上端的item的位置。convertView是指可以重用的视图,即刚刚出队的视图(在上面已经重点讲过)。parent应该就是显示数据的视图(如ListView、GridView等)。

getItem()和getItemId()有什么用呢?我们知道,GridView将View以方格的方式展示出来之后是要与用户交互的(比如点击某张图片),为了更好的相应用户的动作,我们就要用到这两个函数了。

示例

    private class flashAdapter extends BaseAdapter {
        private Context mContext;
        private ArrayList<String> mMode; // String可替换成一个自定义的item对象
        private ViewHolder mViewHolder;

        public flashAdapter(Context mContext, ArrayList<String> mMode) {
            this.mContext = mContext;
            this.mMode = mMode;
        }

        @Override
        public int getCount() {
            return mMode.size();
        }

        @Override
        public Object getItem(int position) {
            return mMode.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (null == convertView) {

                // 对ViewHolder的属性进行赋值
                LayoutInflater layoutInflater = LayoutInflater.from(mContext);
                convertView = layoutInflater.inflate(R.layout.led_item, parent, false);
                mViewHolder = new ViewHolder();
                mViewHolder.mImageView = (ImageView) convertView.findViewById(R.id.ledImage);
                mViewHolder.mTextView = (TextView) convertView.findViewById(R.id.ledMode);
                convertView.setTag(mViewHolder);
            } else {// 如果缓存池中有对应的view缓存,则直接通过getTag取出viewHolder
                mViewHolder = (ViewHolder) convertView.getTag();
            }

            // 设置控件的数据
            mViewHolder.mImageView.setImageResource(R.drawable.record_camera_flash_led);
            mViewHolder.mTextView.setText(mMode.get(position));
            mViewHolder.mTextView.setTextSize(12);

            return convertView;
        }

        // ViewHolder用于缓存控件
        public class ViewHolder {
            public ImageView mImageView;
            public TextView mTextView;
        }
    }

参考:

https://www.cnblogs.com/caobotao/p/5061627.html
https://www.cnblogs.com/tjudzj/p/4371326.html

相关文章: