android--UI--listview使用和优化
来源:互联网 发布:汉王人脸考勤机数据库 编辑:程序博客网 时间:2024/06/05 05:33
listview一般使用步骤:
1.定制实体类,加入要填入list的变量,设置好set,get方法。
2.自定义item布局,根据要填入的数据。
3.自定义适配器类,继承ArrayAdapter。
4.MainActivity中给listview绑定adapter并·添加数据
实体类:
public class Wanwan { private String name; private int imgid; public Wanwan(String name,int imgid){ this.name=name; this.imgid=imgid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getImgid() { return imgid; } public void setImgid(int imgid) { this.imgid = imgid; }}
自定义adpater类
public class WanwanAdapter extends ArrayAdapter<Wanwan> { private int resourceID; public WanwanAdapter(Context context, int textviewresourceid, List<Wanwan> object){ super(context,textviewresourceid,object); resourceID=textviewresourceid; } @Override public View getView(int position, View convertView, ViewGroup parent) { Wanwan wanwan=getItem(position);//获取当前项的wanwan实例 View view= LayoutInflater.from(getContext()).inflate(resourceID,null);//获取view实例 ImageView imgview=(ImageView) view.findViewById(R.id.img_wanwan); TextView textView=(TextView) view.findViewById(R.id.text_wanwan); imgview.setImageResource(wanwan.getImgid()); textView.setText(wanwan.getName()); return view; }}
布局文件:item_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"> <ImageView android:id="@+id/img_wanwan" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/text_wanwan" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>
MainActivity
public class MainActivity extends AppCompatActivity { private List<Wanwan> wananlist=new ArrayList<Wanwan>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iniWanwan();//列表添加数据 WanwanAdapter wanwanAdapter=new WanwanAdapter(MainActivity.this,R.layout.wanwan_item,wananlist); ListView listView=(ListView) findViewById(R.id.listview); listView.setAdapter(wanwanAdapter); } private void iniWanwan(){ for(int i=0;i<100;i++){ wananlist.add(new Wanwan("wanwan", R.mipmap.ic_launcher)); } }}
运行:
关于优化listview
自定义的adapter,会要重写getView方法,在getView方法产生给用户item的视图以及数据。
这里有一个优化的地方,就是重用view,这样减少内存消耗,同时加快item加载速度。
1.使用convertView参数优化
convert参数用于将之前加载好的缓存,重用了,很大程度上的减少了内存的消耗。通过判断convertView是否为null,是的话就需要产生一个视图出来,然后给这个视图数据,最后将这个视图返回给底层,呈献给用户。
特点:如果当前的convertView为null,则通过LayoutInflat产生一个view。
修改adpater代码:
@Override public View getView(int position, View convertView, ViewGroup parent) { Wanwan wanwan = getItem(position);//获取当前项的wanwan实例 View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceID, null);//获取view实例 } else { view = convertView; } ImageView imgview = (ImageView) view.findViewById(R.id.img_wanwan); TextView textView = (TextView) view.findViewById(R.id.text_wanwan); imgview.setImageResource(wanwan.getImgid()); textView.setText(wanwan.getName()); return view; }
2.设置classViewHolder,防止重复寻找控件
上面的写法会有一个缺点,就是每次在getVIew的时候,都需要重新的findViewById,重新找到控件,然后进行控件的赋值以及事件相应设置。这样其实在做重复的事情,因为的geiview中,其实包含有这些控件,而且这些控件的id还都是一样的,也就是其实只要在view中findViewById一次,后面无需要每次都要findViewById了。
所以我们要自定义一个类 ViewHolder
代码修改:
@Override public View getView(int position, View convertView, ViewGroup parent) { Wanwan wanwan = getItem(position);//获取当前项的wanwan实例 View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceID, null);//获取view实例 viewHolder=new ViewHolder(); viewHolder.imageView=(ImageView) view.findViewById(R.id.img_wanwan);//实例化变量 viewHolder.textView=(TextView) view.findViewById(R.id.text_wanwan); view.setTag(viewHolder);//将Viewholder存储在view中 } else { view = convertView; viewHolder=(ViewHolder) view.getTag();//重新获取viewholder } //ImageView imgview = (ImageView) view.findViewById(R.id.img_wanwan); //TextView textView = (TextView) view.findViewById(R.id.text_wanwan); viewHolder.imageView.setImageResource(wanwan.getImgid()); viewHolder.textView.setText(wanwan.getName()); return view; } class ViewHolder{ ImageView imageView; TextView textView; }
PS:以上两种优化方式参考《第一行代码》
3.其他优化建议
1.设置ViewHolder为static,也就是静态的,静态类只会在第一次加载时会耗费比较长时间,但是后面就可以很好帮助加载,同时保证了内存中只有一个ViewHolder,节省了内存的开销。
static class ViewHolder{ ImageView imageView; TextView textView; }
4.大量分批/网络下载
如果有很多item并且需要从网络下载数据的话。一次性全加载不仅浪费时间而且消耗用户流量。
其一:假如网络情况很好,我们使用的手机也许能够一下子加载完所有新闻数据,然后显示在ListView中,用户可能感觉还好,假如说在网络不太顺畅的情况下,用户加载完所有网络的数据,可能这个list是1000条新闻,那么用户可能需要面对一个空白的Activity好几分钟,这个显然是不合适的
其二:我们知道Android虚拟机给每个应用分配的运行时内存是一定的,一般性能不太好的机器只有16M,好一点的可能也就是64M的样子,假如说我们现在要浏览的新闻总数为一万条,即便是网络很好的情况下,我们可以很快的加载完毕,但是多数情况下也会出现内存溢出从而导致应用崩溃的情况。
为此搜索了一下:
原理就是
listview.setOnScrollListener(new scrollListener());
判断滑动的item个数,到一定时候就继续加载。
参考文章:Android: ListView数据的分批加载
实现代码:
footer.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" android:orientation="vertical"> <ProgressBar style="?android:attr/process" android:layout_width="50dp" android:layout_height="wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="18dp" /></LinearLayout>
网络服务类:
public class DataService { /** * * @param startposition * :从第startposition条数据开始加载 * @param pagesize * :每页显示数量 * @return:服务器返回数组 */ public static List<String> getData(int startposition, int pagesize) { List<String> list = new ArrayList<String>(); for (int i = startposition; i <startposition+ pagesize; i++) { list.add("第" + i + "条数据"); } return list; }}
主要代码;
public class MainActivity extends AppCompatActivity {// private List<Wanwan> wananlist=new ArrayList<Wanwan>(); private ListView listview; private List<String> data = new ArrayList<String>(); private ArrayAdapter<String> adapter; private LayoutInflater inflater; private View footer;// 页脚-正在加载中..... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);// iniWanwan();//列表添加数据// WanwanAdapter wanwanAdapter=new WanwanAdapter(MainActivity.this,R.layout.wanwan_item,wananlist);// ListView listView=(ListView) findViewById(R.id.listview);// listView.setAdapter(wanwanAdapter); inflater = getLayoutInflater(); footer = inflater.inflate(R.layout.footer, null); listview = (ListView) findViewById(R.id.listview); listview.setOnScrollListener(new scrollListener()); data.addAll(DataService.getData(0, 20)); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data); /* 在适配器之前加页脚,这样适配器会重新被封装成 '有页脚的适配器' */ listview.addFooterView(footer); listview.setAdapter(adapter); listview.removeFooterView(footer); } /** * listview滚动监听类 * */ public class scrollListener implements AbsListView.OnScrollListener { int pagesize = 20;// 每页显示条目 int maxpage = 5;// 最多页数 int currentpage;// 当前页 int nextpage; boolean finish_load = true;// 加载是否完成,默认完成 /** * 监听滚动状态改变:1-手指正在滑动 2-手指停止滑动 3-组件停止滚动 */ public void onScrollStateChanged(AbsListView view, int scrollState) { } /** * firstVisibleItem:第一个可见item visibleItemCount:可见item数量 * totalItemCount:总条目数量 */ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { final int total = totalItemCount; /* 如果滚动到最后一条 */ if (listview.getLastVisiblePosition() + 1 == totalItemCount) { if (totalItemCount > 0) { /* 获取当前页 */ currentpage = totalItemCount % pagesize == 0 ? totalItemCount / pagesize : totalItemCount / pagesize + 1; nextpage = currentpage + 1; /* * 如果当前页小于规定的最大页数,并且加载完成(不断滚动就会不断执行onScroll方法, * 所以用finish_load锁定翻页) */ if (nextpage <= maxpage && finish_load) { finish_load = false; /* 每次翻页前添加页脚 */ listview.addFooterView(footer); /* 创建子线程,执行翻页 */ new Thread(new Runnable() { public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } List<String> l = DataService.getData(total, pagesize); handle.sendMessage(handle.obtainMessage(123, l)); } }).start(); } } } } /* 通过handle和主线程通讯,主线程接收消息更新UI */ Handler handle = new Handler() { public void handleMessage(Message msg) { data.addAll((List<String>) msg.obj); adapter.notifyDataSetChanged(); /* 页脚显示完就删掉 */ if (listview.getFooterViewsCount() > 0) listview.removeFooterView(footer); finish_load = true; } }; }// private void iniWanwan(){// for(int i=0;i<100;i++){// wananlist.add(new Wanwan("wanwan", R.mipmap.ic_launcher));// }// }}
实现效果;
5.ListView的分页
DEMO下载:
ListView优化
AandroidStudio2.1.2打开
- android--UI--listview使用和优化
- 【Android UI】ListView的使用和简单优化
- listView使用和优化
- [UI]Android列表ListView使用
- Android UI学习之ListView(使用ArrayAdapter和SimpleAdapter)
- Android UI设计——ListView控件使用优化(五)
- Android UI 设计(11):ListView 控件使用优化(五)
- Android UI 优化 使用<include/>和 <merge />标签
- Android UI 优化 使用<include/>和 <merge />标签
- Android UI 优化 使用<include/>和 <merge />标签
- Android UI 使用Merge,include和 ViewStub--优化(1)
- Android UI 优化 使用<include/>和 <merge />标签
- Android UI 优化 使用<include/>和 <merge />标签
- Android使用缓存优化ListView
- Android使用缓存优化ListView
- Android使用缓存优化ListView
- Android使用缓存优化ListView
- Android使用缓存优化ListView
- MySql(21)------mysql索引使用
- 名词解释: amd64fre
- Android数据存储方式(一)文件
- Ajax实现局部刷新和异步处理简单应用(实现简单注册验证)
- Linux进程分配内存的两种方式--brk() 和mmap()
- android--UI--listview使用和优化
- JavaScript 原型中的哲学思想
- 架构师—软件系统实施方案选择
- sizeof大小
- Memcached 服务器 在CentOS6.5中部署
- C++中const的用法
- 3402: [Usaco2009 Open]Hide and Seek 捉迷藏 最短路
- 本地测试服务器环境部署 && iis 信息服务管理
- 二进制转换与此平台上的长模式不兼容