BaseAdapter的使用方法

BaseAdapter是最基础的Adapter类,也是最实用最常用的一个类,但是相比于ArrayAdapter之类的,对初学者来说却比较难理解。所以在这里介绍一下BaseAdapter。

 

Adapter是什么

An Adapter object actsas a bridge between an AdapterView and the underlying data for that view. TheAdapter provides access to the data items. The Adapter is also responsible formaking a View for each item in the data set.

 

翻译过来,简单理解就是adapter是view和数据的桥梁。在一个ListView或者GridView中,你不可能手动给每一个格子都新建一个view,所以这时候就需要Adapter的帮忙,它会帮你自动绘制view并且填充数据。

 

BaseAdapter是什么

从英文就可以知道了,最基础的Adapter,也就是说,它可以做所有的事情。所以为什么说最实用最常用,原因就在于它的全能性,不会像ArrayAdapter等的封装好的类有那么多局限性,但是这样的话,使用起来自然会更加麻烦一点。但是这篇文章就会告诉你怎么熟练使用它。

 

BaseAdapter怎么用

在ListView、GridView或者其他的view中,使用setAdapter方法传入我们的baseAdapter就可以用了。

 

listView.setAdapter(mBaseAdapter);

问题就出在这个mBaseAdapter要怎么写了。重点终于来了。可以新建一个java文件MyBaseAdapter,继承自BaseAdapter,并且实现它的4个基础方法。

 

public classMyBaseAdapter extends BaseAdapter {

    @Override

    public int getCount() {

        return 0;

    }

    @Override

    public Object getItem(int position) {

        return null;

    }

    @Override

    public long getItemId(int position) {

        return 0;

    }

    @Override

    public View getView(int position, ViewconvertView, ViewGroup parent) {

        return null;

    }

}

 

默认实现这4个方法后,接下来我们就要重写这4个方法了。那么具体这4个方法有什么用呢?我们在后面再讲。MyBaseAdapter这个类写好后,我们就新建一个mBaseAdapter,在setAdapter方法的时候传进去就好了。

 

MyBaseAdaptermBaseAdapter = new MyBaseAdapter();

这样的三步法就可以实现BaseAdapter的使用了。但是,这当然没完。因为现在你还没告诉你的BaseAdapter你要叫它干什么呢。所以接下来我们就要修改MyBaseAdapter了。

 

几种listView适配器的用法

@Override

protectedvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//[1]找到我们关心的控件

ListViewlv = (ListView) findViewById(R.id.lv);

 

//设置数据适配器

lv.setAdapter(newMyAdapter());

 

}

privateclass MyAdapter extends BaseAdapter{

 

@Override

publicint getCount() {

return7;

}

 

@Override

publicObject getItem(int position) {

//TODO Auto-generated method stub

returnnull;

}

 

@Override

publiclong getItemId(int position) {

//TODO Auto-generated method stub

return0;

}

 

@Override

publicView getView(int position, View convertView, ViewGroup parent) {

 

//[1]想办法把我们自己定义的布局转换成一个view对象就可以了

Viewview;

if(convertView == null) {

//创建新的view对象   可以通过打气筒把一个布局资源转换成一个view对象

//resource就是 我们定义的布局文件

//获取其他页面布局的三种方式

 

//[一☆☆☆☆]获取打气筒服务

//view =View.inflate(getApplicationContext(), R.layout.item, null);

 

//[二☆☆☆☆]获取打气筒服务

//view =LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);

 

//[三☆☆☆☆]获取打气筒服务

LayoutInflaterinflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

    view = inflater.inflate(R.layout.item,null);

 

 

}else{

//复用历史缓存对象

view= convertView;

 

}

returnview;}}

BaseAdapter方法详解

学会BaseAdapter其实只需要掌握四个方法:getCount, getItem, getItemId, getView

 

getCount:要绑定的条目的数目,比如格子的数量

getItem :根据一个索引(位置)获得该位置的对象

getItemId : 获取条目的id

getView : 获取该条目要显示的界面

可以简单的理解为,adapter先从getCount里确定数量,然后循环执行getView方法将条目一个一个绘制出来,所以必须重写的是getCount和getView方法。而getItem和getItemId是调用某些函数才会触发的方法,如果不需要使用可以暂时不修改。

 

接下来用一个简单的demo来展示一下BaseAdapter。

首先在MyBaseAdapter中添加super()方法,用来将数据源传入MyBaseAdapter中。其中this.data= data;的意思是将传入的形参赋值给我们的私有变量以供使用。mContext是在后面要调用到,这里先不解释。

 

private String[] data;

private ContextmContext;

publicMyBaseAdapter(Context mContext, String[] data) {

    super();

    this.mContext = mContext;

    this.data = data;

}

 

然后就可以将getCount的返回值修改为我们的数据源的长度,要显示几个条目,我们就传入多长的数据源就可以了。

 

public int getCount() {

    return data.length;

}

接着将getView的方法改为显示出我们数据源的字符串。

 

public View getView(intposition, View convertView, ViewGroup parent) {

    TextView textView = new TextView(mContext);

    textView.setText(data[position]);

    return textView;

}

 

这里为每一个条目新建一个TextView用来显示字符串,新建的时候就需要传入一个Context,就用到了我们之前的mContext。这样我们就可以使用MyBaseAdapter来显示一个字符串数组了。不过还需要在前面修改一下,在新建mBaseAdapter的时候要传入context和数据源。

 

String[] strings ={"a","b","c"};

MyBaseAdaptermBaseAdapter = new MyBaseAdapter(getApplicationContext(),strings);

接下来贴一下完整的代码吧。ListView的新建我就不讲了。

 

MainActivity

importandroid.support.v7.app.AppCompatActivity;

importandroid.os.Bundle;

importandroid.widget.ListView;

public classMainActivity extends AppCompatActivity {

  private ListView listView;

  @Override

  protected void onCreate(BundlesavedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_main);

      listView = (ListView)findViewById(R.id.listView);

      String[] strings ={"a","b","c"};

      MyBaseAdapter mBaseAdapter = newMyBaseAdapter(getApplicationContext(),strings);

      listView.setAdapter(mBaseAdapter);

  }

}

MyBaseAdapter部分

importandroid.content.Context;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.widget.BaseAdapter;

importandroid.widget.TextView;

public classMyBaseAdapter extends BaseAdapter {

    private String[] data;

    private Context mContext;

    public MyBaseAdapter(Context mContext,String[] data) {

        super();

        this.mContext = mContext;

        this.data = data;

    }

    @Override

    public int getCount() {

        return data.length;

    }

    @Override

    public Object getItem(int position) {

        return null;

    }

    @Override

    public long getItemId(int position) {

        return 0;

    }

    @Override

    public View getView(int position, ViewconvertView, ViewGroup parent) {

        TextView textView = newTextView(mContext);

        textView.setText(data[position]);

        return textView;

    }

}

 

BaseAdapter进阶使用

当然一个TextView显然满足不了我们的需要,这也完全不能显示BaseAdapter的全能性。那接下来,就来展示一下如何用BaseAdapter显示一个自定义布局。

 

首先新建一个layout,我命名为item,这个就是我们每个条目要展示的布局

 

<?xmlversion="1.0" encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

   xmlns:app="http://schemas.android.com/apk/res-auto"

    android:orientation="horizontal"android:layout_width="match_parent"

   android:layout_height="match_parent">

    <ImageView

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

       app:srcCompat="@mipmap/ic_launcher"

        android:id="@+id/imageView"/>

    <Button

        android:text="Button"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:id="@+id/button"/>

    <TextView

        android:text="TextView"

       android:layout_width="wrap_content"

       android:layout_height="wrap_content"

        android:id="@+id/textView"/>

</LinearLayout>

 

接下来修改getView方法,让它显示我们这个item布局

 

public View getView(intposition, View convertView, ViewGroup parent) {

    LayoutInflater inflater =LayoutInflater.from(mContext);

    View view =inflater.inflate(R.layout.item,null);

    final TextView textView = (TextView)view.findViewById(R.id.textView);

    Button button = (Button)view.findViewById(R.id.button);

    ImageView imageView = (ImageView)view.findViewById(R.id.imageView);

   imageView.setImageResource(R.mipmap.ic_launcher);

    button.setOnClickListener(newView.OnClickListener() {

        @Override

        public void onClick(View v) {

            textView.append("!");

        }

    });

    textView.setText(data[position]);

    return view;

}

主要讲解一下前两句。LayoutInflater是用来加载布局的,用LayoutInflater的inflate方法就可以将你的item布局绘制出来。其中getView方法中的三个参数,position是指现在是第几个条目;convertView是旧视图,就是绘制好了的视图;parent是父级视图,也就是ListView之类的。用inflate方法绘制好后的view最后return返回给getView方法就可以了。

 

BaseAdapter的优化使用

上面的convertView是旧视图是什么意思呢?就是listview如果超出了屏幕,滑动的时候会隐藏掉一部分,这时候就将隐藏掉的部分保存到convertView中。那么如果是我们之前的写法,每次返回的时候就没有使用convertView,重新创建了一个View,这样子浪费了系统资源。那要怎么利用convertView优化呢?同样我们还是对getView进行进一步修改。

 

首先定义一个类ViewHolder,用来标记我们的控件

static classViewHolder{

    TextView textView;

    ImageView imageView;

    Button button;

}

接下来使用ViewHolder优化

在getView方法中,Adapter先从xml中用inflate方法创建view对象,然后在这个view找到每一个控件。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个控件都放在Holder中,当第一次创建convertView对象时,把这些控件找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以。

 

public View getView(intposition, View convertView, ViewGroup parent) {

    LayoutInflater inflater =LayoutInflater.from(mContext);

    ViewHolder holder = null;

    if (convertView == null) {

        convertView =inflater.inflate(R.layout.item, null);

        holder = new ViewHolder();

        holder.button = (Button)convertView.findViewById(R.id.button);

        holder.textView = (TextView)convertView.findViewById(R.id.textView);

        holder.imageView = (ImageView)convertView.findViewById(R.id.imageView);

        convertView.setTag(holder);

    }   else {

        holder = (ViewHolder)convertView.getTag();

    }

   holder.imageView.setImageResource(R.mipmap.ic_launcher);

    holder.button.setOnClickListener(newView.OnClickListener() {

        @Override

        public void onClick(View v) {

           Log.d("click","button");

        }

    });

    holder.textView.setText(data[position]);

    return convertView;

}

 

先判断convertView是否为空,是的话就创建ViewHolder,不是的话就取出ViewHolder,这样就可以实现复用convertView了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值