安卓listView不得不说的那些细节
来源:互联网 发布:网站排名seo 编辑:程序博客网 时间:2024/05/27 01:17
众所周知,ListView是一个在垂直滚动的列表中显示条目的控件,我们在开发ListView中,我们只需要按照如下步骤来操作即可实现ListView
- 在xml布局中添加listView控件
- 实例化这个控件,
- 实现ListAdapter接口给ListView提供数据,绝大多数情况下(说所有的也不过分)只需要继承Android系统提供好的BaseAdapter这个抽象类,并且实现其中的四个抽象方法即可,四个抽象方法分别为:
a) getCount():返回值代表在ListView中显示的条目数
b) getItem(int i):返回在i位置上的条目的javaBean对象
c) getItemId(int i):返回某条目的id
d)getView(int position, View convertView, ViewGroup viewGroup):告诉listview条目上显示的内容;返回一个View对象作为条目上的内容展示,该方法返回什么样的view,Listview的条目上就显示什么样的view。必须实现。屏幕上每显示一个条目getview方法就会被调用一次;convertView:曾经使用过的view对象,可以被重复使用,使用前要判断。
至于ListView的具体使用,不想赘述,不清楚的同学请自行网补,今天要说的主要是getView方法的一些细节。
首先,正如上文我们提到的一样,getView方法放回一个View对象作为ListView上显示的条目,这个方法返回什么View,那么ListView上就显示什么View,我们不妨先写一个例子
xml布局代码如下
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/lv_simple" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView></LinearLayout>
很简单,布局中只放了一个ListView控件,布局高度和布局宽度充满父窗口,在看我们的java代码
/** * Created by xdq on 2016/8/23. */public class GetViewActivity extends AppCompatActivity { private final static String TAG = "TAG"; private Context mContext; @BindView(R.id.lv_simple) ListView lvSimple; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_getview); ButterKnife.bind(this); mContext = this; MyAdapter adapter = new MyAdapter(); lvSimple.setAdapter(adapter); } class MyAdapter extends BaseAdapter{ private Map<Object,Object> map = new HashMap<>(); @Override public int getCount() { return 20; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int postion, View covertView, ViewGroup viewGroup) { TextView view = new TextView(mContext); map.put(view.hashCode(),""); Log.i(TAG,"总共创建了:"+map.size()+"个View对象"); view.setText("postion:"+(postion+1)); view.setTextSize(30); return view; } }}
我们在adapter中使用了一个map对象来存放我们getView方法创建的View对象的hashcode,更具map的key的唯一性来获知我们创建了多少个View对象,我们看一下,activity刚启动的时候的结果,
可以看到,整个屏幕总共显示出来了13个条目。
接下来我们再看一看log打印
我们发现此时一共创建了13个View对象,跟我们屏幕上显示的View条目数一致。(需要注意的是:位置13的条目虽然只显示了一部分,但是这个View对象已经创建了 。不然你又怎么能看到他的一部分呢?。。。。废话。。。)
接下来,我们拖动listView上下滚动,再来看看日志打印的效果。。。
omg~~随着我们不断的滚动ListView,我们呢发现getView方法也跟随者被执行,并且在不断的创建新的对象,很显然,这个方式是不科学的,
那么有什么办法改进呢?
文章一开始我们在说getview方法的时候,我们着重强调了convertView这个参数股,google也为我们考虑到了这个问题,所以他给出这个参数用来缓存上一个被隐藏的View对象。
我们修改一下java代码如下:
/** * Created by xdq on 2016/8/23. */public class GetViewActivity extends AppCompatActivity { private final static String TAG = "TAG"; private Context mContext; @BindView(R.id.lv_simple) ListView lvSimple; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_getview); ButterKnife.bind(this); mContext = this; MyAdapter adapter = new MyAdapter(); lvSimple.setAdapter(adapter); } class MyAdapter extends BaseAdapter{ private Map<Object,Object> map = new HashMap<>(); @Override public int getCount() { return 20; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int postion, View covertView, ViewGroup viewGroup) { TextView view = null; if (covertView!=null){ view = (TextView) covertView; }else { view = new TextView(mContext); } map.put(view.hashCode(),""); Log.i(TAG,"总共创建了:"+map.size()+"个View对象"); Iterator i = map.entrySet().iterator(); while(i.hasNext()){ Object o = i.next(); String key = o.toString(); Log.i(TAG,"键值为"+key); } view.setText("postion:"+(postion+1)); view.setTextSize(90); return view; } }}
这里我们复用一下covertView,当然使用前需要做一下非空判断。
我们把textsize设置为90,使得一屏幕显示的条目减少,省得打印太多看不清楚。。。
这个activity刚开始启动时,效果跟上面一样这里不再重复
,接下来我们把listview往下滑动到第一个未显示出来的条目,如下
第四个位置的条目已经创建好了。我们看log:
红色箭头标识的即为我们第四个条目显示出来的view对象的hashcode同时我们呢看到,此时我们一共创建了四个View对象,接下来我们再滚到到第五个条目,再看log:
此时,我们发现getView并没有创建新的View对象,而是开始复用了,看第五个条目的对象的hashcode值正好是与刚刚滚出的第一个条目的hashcode值是一抹一样的,那么也正是我们第五个条目复用了刚刚隐藏的第一个条目的View对象,之后我们无论在怎么滚动ListView我们发现系统维护的对象只有四个了,
结论就是当我们采用这个方式复用View的时候,我们只需要维护屏幕显示的条目个数+1个View对象即可,并且每次调用getview的时候,复用的正是刚刚被隐藏的那个view对象,不知道机智的你是否已经看明白了,,那么再让你写个viewholder是否小菜一碟了呢?
ok,就扯这点儿 老鸟勿喷。。。。。
- 安卓listView不得不说的那些细节
- 内容详情页优化那些不得不说的细节
- 这四年不得不说的那些事
- IE6不得不说的那些BUG
- 不得不说的opencv 那些事
- 唐骏:这四年不得不说的那些事
- 我与朗科不得不说的那些事儿
- 和小媳妇的那些不得不说的事
- 关于豆瓣不得不说的那些事儿
- Android Service那些不得不说的事-之一
- 做好用户体验不得不说的那些事
- 关于简历不得不说的那些事儿
- 不得不说的那些坑(一)
- Java中那些不得不说的坑
- printf与a++那些不得不说的事儿
- java异常那些不得不说的事
- 那些不得不注意的编码细节
- with和有名function那些不得不说的事....
- 初见spark streaming之JavaNetWorkWordCount
- Mysql 重置密码
- 我要开始学习爬虫啦
- 软件测试(2)
- 用Java代码通过JDBC连接Hiveserver2
- 安卓listView不得不说的那些细节
- ExpandableTextView 可展开和收缩内容的TextView。
- Android应用配置错误导致不能编译--配成系统应用
- Java面试题整理
- 把多个源码编译成一个ko文件的方法
- (1)RobView 环境搭建
- 欢迎使用CSDN-markdown编辑器
- ES6学习笔记
- 时间戳相关