ListView的Adapter

**

关于ListView控件的适配器Adapter

**

本人也只是刚刚接触安卓开发,就想对用的比较多的ListView开始进行一点知识的整理。就拿自己写的一个消息列表来作为例子来整理一波吧。

在主活动的布局文件中就只需要加入一个ListView的控件。

<ListView
    android:layout_marginTop="5dp"
    android:dividerHeight="5dp"
    android:divider="#99d9db"
    android:id="@+id/lv_msg"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</ListView>

这里也没什么好讲的…

然后我们再来定义一波ListView中的item布局,我在这里只是简单地设置了一个头像的ImageView、一个用户名的TextView和一条内容的TextViews并为之一一设置ID。

<LinearLayout
    android:layout_marginTop="5dp"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:gravity="center"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/iv_head"
            android:layout_width="65dp"
            android:layout_height="55dp" />

    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_weight="4"
        android:layout_width="0dp"
        android:layout_height="60dp">

        <TextView
            android:id="@+id/tv_name"
            android:layout_marginTop="5dp"
            android:layout_marginLeft="5dp"
            android:layout_width="100dp"
            android:layout_height="20dp" />

        <TextView
            android:id="@+id/tv_msg"
            android:maxLines="1"
            android:layout_marginTop="2dp"
            android:layout_marginLeft="5dp"
            android:layout_width="match_parent"
            android:layout_height="30dp" />

    </LinearLayout>

</LinearLayout>

接下来就是重头戏了——一个自定义的适配器

这也是我今天挺想去总结的一个点,因为我个人觉得适配器就是一个ListView的灵魂,操控着它的数据更新、操控着它的视图展示等等。

常用的适配器有BaseAdapter,ArrayAdapter,SimpleAdapter等等。而SimpleAdapter在三者中又用的是比较少的,因为SimpleAdapter已经在内部被写好,改动的地方比较少,因此灵活性较低,不宜被继承改动。而ArrayAdapter则是由BaseAdapter派生而来,具有BaseAdapter的全部功能,再加上继承自ArrayAdapter的适配器在实例化时可直接使用泛型构造,从而使自定义适配器更加灵活。而在本例中的适配器继承的便是ArrayAdapter(因为使用了自定义的一个Msg类。)。

private int resourceId;
private List<Msg> message = new ArrayList<Msg>();

public MsgAdapter(@NonNull Context context, @LayoutRes int resource) {
    super(context, resource);
    resourceId = resource;
}

public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull List<Msg> objects) {
    super(context, resource, objects);
    resourceId = resource;
    this.message = objects;
}

public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
    super(context, resource, textViewResourceId);
}

public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull Msg[] objects) {
    super(context, resource, objects);
}

public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull Msg[] objects) {
    super(context, resource, textViewResourceId, objects);
}

public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull List<Msg> objects) {
    super(context, resource, textViewResourceId, objects);
}

可见,在继承了ArrayAdater后,IDE会提示你要创建构造方法,而该适配器有6种构造方法。其中的几个参数如context指依附的活动,resource指加载item的布局id,List object则指列表中的对象等等就不一一赘述了,毕竟见名知意。

而在自定义的adapter中还可以重写内部方法。

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

此方法实现了加载每一个item的布局的功能,最终返回的是一个View对象,通常与类ViewHolder连用。此类只定义item的布局中存在的控件,以方便在加载整个列表布局时,更加快速地从类里取出存在的item布局。即若某个item的布局若存在于ViewHolder,则不需再重新实例一个新的对象,重新加载该item布局,而是从ViewHolder中取出该item的布局,直接展示在ui层。

public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    View item;
    ViewHolder mViewHolder;
    //获取当前位置的position以填充布局
    Msg msg = getItem(position);
    //如果当前view为空,则将当前view填充入viewholder中,否则从viewholder中回调出来
    if (convertView == null) {
        //将当前view加载出来
        item = LayoutInflater.from(getContext()).inflate(resourceId, null);
        mViewHolder = new ViewHolder();
        mViewHolder.head = (ImageView) item.findViewById(R.id.iv_head);
        mViewHolder.name = (TextView) item.findViewById(R.id.tv_name);
        mViewHolder.msg = (TextView) item.findViewById(R.id.tv_msg);
        item.setTag(mViewHolder);
    } else {
        item = convertView;
        mViewHolder = (ViewHolder) item.getTag();
    }

    mViewHolder.head.setImageResource(msg.getImageResource());//设定头像
    mViewHolder.name.setText(msg.getName());//设定用户名
    mViewHolder.msg.setText(msg.getMsg());//设定消息

    return item;
}

(二)public int getCount()、public int getPosition(T item)、public T getItem(int position)

这些方法分别是获取整个列表的长度,即item的数目,一般返回的是mList.size();获取当前item的位置,返回的是item在列表的位置;获取当前位置的item,返回的是position中对应的item对象。

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

//获取item的位置

@Override
public int getPosition(@Nullable Msg item) {
    return super.getPosition(item);
}

//获取当前位置的item

@Nullable
@Override
public Msg getItem(int position) {
    return super.getItem(position);
}

(三)public void notifyDataSetChanged()

这个方法是用来刷新列表的。比如当你需要删除列表中的某个item时,点击删除后若当前的适配器没有调用此方法(即没有mAdapter.notifyDataSetChanged()),IDE会报错。而这个方法也可以在Activity的onResume()方法中调用,从而在跳转过程后,回到当前页面仍然保持最新的列表状态。

@Override
public void notifyDataSetChanged() {
    super.notifyDataSetChanged();
}

整个MsgAdapter代码如下:

/**
  * Created by Carson on 2017/7/15.
  */

public class MsgAdapter extends ArrayAdapter<Msg>{

    private int resourceId;
    private List<Msg> message = new ArrayList<Msg>();

    public MsgAdapter(@NonNull Context context, @LayoutRes int resource) {
        super(context, resource);
        resourceId = resource;
    }

    public MsgAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull List<Msg> objects) {
        super(context, resource, objects);
        resourceId = resource;
        this.message = objects;
    }

    //创建item的临时存储器,提升上下拉动时的加载的速度
    class ViewHolder {
        ImageView head;
        TextView name, msg;
    }

    //获取列表的个数

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

    //获取item的位置

    @Override
    public int getPosition(@Nullable Msg item) {
        return super.getPosition(item);
    }

    //获取当前位置的item

    @Nullable
    @Override
    public Msg getItem(int position) {
        return super.getItem(position);
    }


    //获取item的view

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View item;
        ViewHolder mViewHolder;
        //获取当前位置的position以填充布局
        Msg msg = getItem(position);
        //如果当前view为空,则将当前view填充入viewholder中,否则从viewholder中回调出来
        if (convertView == null) {
            //将当前view加载出来
            item = LayoutInflater.from(getContext()).inflate(resourceId, null);
            mViewHolder = new ViewHolder();
            mViewHolder.head = (ImageView) item.findViewById(R.id.iv_head);
            mViewHolder.name = (TextView) item.findViewById(R.id.tv_name);
            mViewHolder.msg = (TextView) item.findViewById(R.id.tv_msg);
            item.setTag(mViewHolder);
        } else {
            item = convertView;
            mViewHolder = (ViewHolder) item.getTag();
        }

        mViewHolder.head.setImageResource(msg.getImageResource());//设定头像
        mViewHolder.name.setText(msg.getName());//设定用户名
        mViewHolder.msg.setText(msg.getMsg());//设定消息

        return item;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }
}

Activity的代码:

public class MsgActivity extends AppCompatActivity {

    private List<Msg> mList;
    private MsgAdapter mAdapter;
    private ListView mListView;

    //随机定义一些图片、用户名、内容
    private int []head = {
            R.drawable.recommend_head1,
            R.drawable.recommend_head2,
            R.drawable.recommend_head3,
            R.drawable.recommend_head4
    };

    private String []name = {
            "King",
            "Lily",
            "July",
            "Kelvin"
    };

    private String []message = {
            "I am message one.",
            "I am message two.",
            "I am message three.",
            "I am message four."
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_msg);

        initViews();

    }

    private void initViews() {
        mList = new ArrayList<Msg>();
        mAdapter = new MsgAdapter(this, R.layout.layout_msg, mList);
        mListView = (ListView) findViewById(R.id.lv_msg);

        mListView.setAdapter(mAdapter);

        Random r = new Random();

        //可以从这里初始化listView
        for (int i = 1; i <= 10; i++){
            Msg msg = new Msg(head[r.nextInt(4)], "" + name[r.nextInt(4)], "" + message[r.nextInt(4)]);
            //将实例化后的对象加入到list中,然后list通过adapter适配于listview中
            mList.add(msg);
        }

    }
}

当然个人只是处于初学地步,若有错误也请各位大牛指点一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值