ListView基本使用
来源:互联网 发布:知乎是什么类型的网站 编辑:程序博客网 时间:2024/06/16 14:12
珍惜作者劳动成果 转载请注明出处
学过ListView的人都知道, 它在Android学习中有着举足轻重的地位, 虽然现在有了RecyClerView来替代ListView, 但是对于我们初学者来说, 了解和使用ListView还是非常重要的!!!
我们应该知道, 显示复杂内容的控件一般会有一个Adapter来控制它的显示. 这其实就是我们平常所说的MVC设计模式. Adapter就扮演了Controller的角色.
在具体实现之前我们要从大方向上来了解一下ListView的实现机制.
ListView是用来显示数据的控件, 在xml布局文件中存放(当然也可以用Java代码实现, 就不要这么钻牛角尖了^v^), 所以它需要有数据源, 才能显示数据, 但是它也需要知道我们的数据怎样展示在手机上, 这就用到了我们的Adapter. 好,先简单介绍到这儿, 后面会有详细的阐述.
实现ListView的几种简单的方式
接下来, 我先介绍几种实现ListView非常简单的方式, 不过这几种在我们后来的工作, 项目中几乎不用, 所以我也不做过多的解释.
直接在XML文件中指定数据源.
<ListView android:entries="@array/entry" ... />
简单到没朋友, 后期几乎没用
ArrayAdapter的实现方式
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list);ListView listView = (ListView) findViewById(R.id.main_listview);listView.setAdapter(adapter);
不解释
SimpleAdapter实现方式
它虽然叫简单Adapter, 但是还是比ArrayAdapter复杂点, 灵活性要高些,因为用到机率也不大, 所以不解释了, 自己可以看看使用方式
//只能用id或本地SimpleAdapter adapter = new SimpleAdapter(this, list,R.layout.item, new String[]{"title", "img"}, new int[]{R.id.item_tv, R.id.item_iv});adapter.setViewBinder(new SimpleAdapter.ViewBinder() { @Override//返回值: 是否绑定完成 public boolean setViewValue(View view, Object data, String textRepresentation) { switch (view.getId()){ //绑定ImageView case R.id.item_iv: ImageView imageView = (ImageView) view; String url = (String) data; new ImageLoader(imageView).execute(url); return true; } return false; }});
使用BaseAdapter实现ListView
我们现在前面做理论说明, 整理好后代码在最后贴出
简单介绍
首先我们写个类(MyAdapter) extents BaseAdapter, 因为BaseAdapter为抽象类, 所以需要实现父类的四个方法
@Override//返回数据的数量public int getCount() { return 0;}@Override//返回当前数据的对象, 参数: 位置public Object getItem(int position) { return null;}@Override//返回当前数据对象的id(如果没有可以直接返回position) //参数: 位置public long getItemId(int position) { return 0;}/* 在这里非常重要的方法, 每次item(数据项)显示在手机上时都会调用一次getView, 也就是说它返回的View就是每次显示在手机上的item*/@Override//参数: 位置, 复用的View(一边item出去后,再次调用时会传入该item), 父控件public View getView(int position, View convertView, ViewGroup parent) { return null;}
ListView优化方案
1, listView布局的高度必须是定值或match_parent 先去取第1个条目的高度和第2个条目想加,... 计算自身的高度, 所以不要使用wrap_content2, convertView的复用3, 减少findViewById的使用次数
尽量减少自己去控制数据源!!(符合MVC设计模式)
贴出代码, 一般一个完整的Adapter就是下面的格式
public class MyAdapter extends BaseAdapter{ private final LayoutInflater inflater; private Context context; private List<Entry> list; public MyAdapter(Context context, List<Entry> list) { this.context = context; this.list = list; inflater = LayoutInflater.from(context); } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override //位置 //重复利用的控件 //父控件 public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = inflater.inflate(R.layout.item, parent, false); convertView.setTag(new ViewHolder(convertView)); } ViewHolder holder = (ViewHolder) convertView.getTag(); Entry entry = list.get(position); ImageUtil.loadImage(holder.image, "http://tnfs.tngou.net/image" + entry.getImgURL()); return convertView; } //批量添加 public void addAll(Collection<? extends Entry> collection){ list.addAll(collection); notifyDataSetChanged(); } //数据清理 public void clear() { list.clear(); notifyDataSetChanged(); } //就是View的持有 public static class ViewHolder { private final TextView text; private final ImageView image; public ViewHolder(View itemView) { text = ((TextView) itemView.findViewById(R.id.item_tv)); image = ((ImageView) itemView.findViewById(R.id.item_iv)); } }}
到目前为止我们可以解决显示本地图片问题, 但是我们加载网络数据(尤其是图片)还是有问题的
解决item显示图片错位的问题和图片缓存问题 (Lru算法缓存机制)
细心的朋友会发现, 在上面的代码中, 有下面一句 :
ImageUtil.loadImage(holder.image, "http://tnfs.tngou.net/image" + entry.getImgURL());
里面的代码已经解决了这个问题, 我将会把源码上传到云盘供大家下载, 我在源码中已经加上了注释 https://yunpan.cn/cMzI4y8SykZrR 访问密码 e1dc
自己封装BaseAdapter
BaseAdapter中有很多代码都可以复用, 所以我们写一个通用的Adapter
package com.lulu.day26_listview;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.ParameterizedType;import java.net.IDN;import java.util.Collection;import java.util.List;/** * Created by Lulu on 2016/9/2. */public abstract class CommonAdapter<D, VH extends CommonAdapter.ViewHolder> extends BaseAdapter { private final LayoutInflater inflater; private Context context; private int layoutId; //数据源 private List<D> list; public CommonAdapter(Context context, int layoutId, List<D> list) { this.context = context; this.layoutId = layoutId; this.list = list; inflater = LayoutInflater.from(context); } @Override public int getCount() { return list.size(); } @Override public D getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { D d = list.get(position); Class<?> aClass = (Class<?>) d.getClass(); Field id = null; try { id = aClass.getField("id"); } catch (NoSuchFieldException e) { e.printStackTrace(); } if (id == null) { try { id = aClass.getDeclaredField("id"); } catch (NoSuchFieldException e) { e.printStackTrace(); } } if (id != null) { try { return (long) id.get(d); } catch (IllegalAccessException e) { e.printStackTrace(); } } Method getId = null; try { getId = aClass.getMethod("getId"); } catch (NoSuchMethodException e) { e.printStackTrace(); } if (getId == null) { try { getId = aClass.getDeclaredMethod("getId"); } catch (NoSuchMethodException e) { e.printStackTrace(); } } if (getId != null) { try { return (long) getId.invoke(id); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = inflater.inflate(layoutId, parent, false); //如何获取Vh怎样获取它的子类呢? Class type = (Class) ((ParameterizedType) getClass() .getGenericSuperclass()) .getActualTypeArguments()[0]; try { Constructor constructor = type.getConstructor(View.class); Object o = constructor.newInstance(convertView); convertView.setTag(o); } catch (Exception e) { e.printStackTrace(); } } onBindView(list.get(position), (VH) convertView.getTag()); return convertView; } public abstract void onBindView(D data, VH holder); public static class ViewHolder { private View itemView; public ViewHolder(View itemView) { this.itemView = itemView; } } public void addAll(Collection<? extends D> collection) { list.addAll(collection); notifyDataSetChanged(); } public void clear() { list.clear(); notifyDataSetChanged(); } public void add(D d) { list.add(d); notifyDataSetChanged(); } public void add(int index, D d) { list.add(index, d); notifyDataSetChanged(); } public void remove (D d) { list.remove(d); notifyDataSetInvalidated(); } public void remove (int index) { list.remove(index); notifyDataSetInvalidated(); }}
- Listview 的基本使用
- listview的基本使用
- ListView 基本使用
- ListView基本使用
- ListView基本使用
- ListView基本使用
- ListView基本使用
- Android ListView基本使用
- listview的基本使用,listview的优化
- ListView的基本使用技巧
- 安卓-ListView基本使用
- 【Android 开发教程】ListView的基本使用
- (Android review)ListView的基本使用
- 可拖拽listview基本使用技巧(DragSortListView)
- ListView的基本使用与优化
- 可拖拽listview基本使用技巧(DragSortListView)
- android学习之ListView的基本使用
- ListView的基本使用与优化
- Hibernate连接mysql数据库并自动创建表
- 大学生爱情兵法-洪亚非-听课笔记
- Android02_Activity
- 聊天室
- Tomcat运行的端口被别的程序占用
- ListView基本使用
- Android01_Android入门
- hrbust 1241 Blocks【暴力枚举+简单优化】
- Linux时钟精度:毫秒?微妙?纳秒?
- LRU算法实践分析
- Invalid property 'maxActive' of bean class [redis.clients.jedis.JedisPoolConfig]: Bean property
- BitMap
- ListView的进阶-跳转 下拉 上拉 多布局重用
- 菜鸟排序之选择与冒泡