ListView的自定义适配器及其优化(listView序号混乱问题的处理)
ListView是最常使用的android组件之一,关于listView的优化问题刚刚了解了一些,在这里做出总结。
PS:如果想让ListView中的item根据数据内容显示item的大小,需要在item.xml中增加下面一句话就可以了(是在整体的布局文件上加):
android:minHeight="?android:attr/listPreferredItemHeight"
<?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:id="@+id/item"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal" >
</LinearLayout>
优化前的自定义适配器:
package com.anhua.adapter; import java.util.List;
import java.util.Map; import com.anhua.bean.LocalHuoDanBean;
import com.example.imooc_weixinfragment.R; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; public class HuoChangAadpter extends BaseAdapter {
private TextView title;// 承运号
private TextView number;// 缺货件数
private TextView no;//序号
private List<Map<String, Object>> arrayList;
private Context context;// 运行上下文
private int item;
private LayoutInflater inflater;
public HuoChangAadpter(List<Map<String, Object>> arrayList, int item,
Context context) {
this.arrayList = arrayList;
this.context = context;
this.item = item;
this.inflater = LayoutInflater.from(context);// 创建视图容器并设置上下文
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arrayList.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(item, null);
title = (TextView) convertView.findViewById(R.id.chengyun);
number = (TextView) convertView.findViewById(R.id.number);
no=(TextView) convertView.findViewById(R.id.no);
}
String titles = arrayList.get(position).get("ID").toString();// 承运号
String numbers = arrayList.get(position).get("quantity").toString();// 缺货件数
String nos=(position+1)+"";
no.setText(nos);
title.setText(titles);
number.setText(numbers);
return convertView;
}
}
我之前一直是使用上面的代码来写自定义适配器的,但是这种方式仅仅限于一些简单的Item组件。最近遇到了给listView的数据增加序号排序的问题,使用优化前的代码直接造成序号的书序错乱,而使用下面的优化后的代码序号排序错乱问题就解决了。
优化后的自定义适配器:
package com.anhua.adapter; import java.util.List;
import java.util.Map; import com.anhua.bean.LocalHuoDanBean;
import com.example.imooc_weixinfragment.R; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; public class HuoChangAadpter extends BaseAdapter { private List<Map<String, Object>> arrayList;
private Context context;// 运行上下文
private int item;
private LayoutInflater inflater; public HuoChangAadpter(List<Map<String, Object>> arrayList, int item,
Context context) {
this.arrayList = arrayList;
this.context = context;
this.item = item;
this.inflater = LayoutInflater.from(context);// 创建视图容器并设置上下文
} @Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arrayList.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(item, null);
holder = new ViewHolder(); holder.title = (TextView) convertView.findViewById(R.id.chengyun);
holder.number = (TextView) convertView.findViewById(R.id.number);
holder.no = (TextView) convertView.findViewById(R.id.no);
convertView.setTag(holder);
} else {
// viewHolder被复用
holder = (ViewHolder) convertView.getTag();
}
String titles = arrayList.get(position).get("ID").toString();// 承运号
String numbers = arrayList.get(position).get("quantity").toString();// 缺货件数
String nos = (position + 1) + "";
holder.no.setText(nos);
holder.title.setText(titles);
holder.number.setText(numbers);
return convertView;
} private class ViewHolder {
private TextView title;// 承运号
private TextView number;// 缺货件数
private TextView no;// 序号
}
}
其实对于listView的优化方案可以从以下角度来考虑:
- 1.在adapter中的getView方法中尽量少使用逻辑
- 2.尽最大可能避免GC
- 3.滑动的时候不加载图片
- 4.将ListView的scrollingCache和animateCache设置为false
- 5.item的布局层级越烧越好
- 6.使用ViewHolder
1.在adapter中的getView方法中尽量少使用逻辑
不要在你的getView()中写过多的逻辑代码,我们可以将这些代码放在别的地方,例如:
优化前的getView():
@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
Object current_event = mObjects.get(position);
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.row_event, null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
convertView.setTag(holder); } else {
holder = (ViewHolder) convertView.getTag();
} //在这里进行逻辑判断,这是有问题的
if (doesSomeComplexChecking()) {
holder.ThreeDimention.setVisibility(View.VISIBLE);
} else {
holder.ThreeDimention.setVisibility(View.GONE);
} // 这是设置image的参数,每次getView方法执行时都会执行这段代码,这显然是有问题的
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams); return convertView;
}
优化后的getView():
@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
Object object = mObjects.get(position);
ViewHolder holder = null; if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.row_event, null);
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
//设置参数提到这里,只有第一次的时候会执行,之后会复用
RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
holder.EventPoster.setLayoutParams(imageParams);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
} // 我们直接通过对象的getter方法代替刚才那些逻辑判断,那些逻辑判断放到别的地方去执行了
holder.ThreeDimension.setVisibility(object.getVisibility()); return convertView;
}
2.GC 垃圾回收器
当你创建了大量的对象的时候,GC就会频繁的执行,所以在getView()方法中不要创建很多的对象,最好的优化是,不要在ViewHolder以外创建任何对象,如果你的你的log里面发现“GC has freed some memory”频繁出现的话,那你的程序肯定有问题了。你可以检查一下:
a) item布局的层级是否太深
b) getView()方法中是否有大量对象存在
c) ListView的布局属性
3.加载图片
如果你的ListView中需要显示从网络上下载的图片的话,我们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要再监听器里面监听ListView的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片
listView.setOnScrollListener(new OnScrollListener() { @Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
//停止加载图片
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
imageLoader.stopProcessingQueue();
} else {
//开始加载图片
imageLoader.startProcessingQueue();
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub }
});
4.将ListView的scrollingCache和animateCache设置为false
scrollingCache: scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。
animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉
优化前的ListView
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:smoothScrollbar="true"
android:visibility="gone" />
优化后的ListView
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/list_background_color"
android:dividerHeight="0dp"
android:listSelector="#00000000"
android:scrollingCache="false"
android:animationCache="false"
android:smoothScrollbar="true"
android:visibility="gone" />
5.减少item的布局的深度
我们应该尽量减少item布局深度,因为当滑动ListView的时候,这回直接导致测量与绘制,因此会浪费大量的时间,所以我们应该将一些不必要的布局嵌套关系去掉。减少item布局深度
6.使用ViewHolder
这个大家应该非常熟悉了,但是不要小看这个ViewHolder,它可以大大提高我们ListView的性能
ListView的优化我们已经讲完了,如果在你的项目中,这些基本优化你还没有做到的话,那么你的ListView是有问题的,还有很大的提升潜力,以后再使用ListView的时候,一定要将这几点考虑进去,发挥它的最大的性能。
参考文章:http://blog.csdn.net/nugongahou110/article/details/47128125
ListView的自定义适配器及其优化(listView序号混乱问题的处理)的更多相关文章
- 细解ListView之自定义适配器
下面我们将以一个例子来讲述ListView之自定义适配器 首先我们看一下效果图: [分析] 首先:需要创建一个ListView控件,自定义适配器是为了实现自定义ListView的ListView_It ...
- ListView(下)自定义适配器
(一) 1.效果图 2.activity_main.xml <?xml version="1.0" encoding="utf-8"?> <L ...
- Android -- ListView(SimpleAdapter) 自定义适配器
aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA ...
- ListView使用自定义适配器的情况下实现适配器的文本和图标控件点击事件执行Activity界面中的方法
ListView使用的是自定义适配器,列表项的布局文件中含有文本和图标,实现文本区域和图标区域的点击事件. 实现思路:在自定义适配器MyArrayAdapter 类型中自定义接口和接口方法,分别设置文 ...
- ListView使用自定义适配器的情况下实现适配器的控件点击事件执行Activity界面中的方法
如果ListView使用的是自定义的适配器,比如MyArrayAdapter extends ArrayAdapter<String> 那么,如何实现适配器中的点击事件执行activity ...
- 安卓开发_浅谈ListView(自定义适配器)
ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果 有这样一个Demo ...
- (转)Android之自定义适配器
ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果. 有这样一个Demo ...
- 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)
1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/and ...
- 打造android偷懒神器———ListView的万能适配器
如果你去做任何一个项目,我相信你都会跟我有一样的经历,最最普遍的就是列表显示ListView,当然,写N个自定义的适配器也是情理之中.虽说程序员本身就是搬砖,做这些枯燥无味的重复的事情也是理所当然,但 ...
随机推荐
- 23.week4
调通了 剩下的就是核心的部分
- 用R理解统计学
1.随机变量( random variable)概念的引入 该数据来自杰克逊实验室.2组数据,每组12只老鼠,一组普通食物,另一组高脂肪(hf)饮食.几周后,科学家们称了每只老鼠的体重,得到了这个数据 ...
- CGLIB代理基础
本文意在讲解CGLIB的基础使用及基本原理. 一.CGLIB的基本原理: 依赖ASM字节码工具,通过动态生成实现接口或继承类的类字节码,实现动态代理. 针对接口,生成实现接口的类,即implement ...
- uuid生成工具类
public class UUIDTool { public static String getUUID() { return UUID.randomUUID().toString().replace ...
- 无线渗透wpa加密路由器
破解wpa加密路由器的原理不同于破解wep加密路由器,只能通过暴力破解获取. 但是获取握手keystream的原理差不多 首先杀死可能会和破解冲突的进程 airmon-ng check kill 开启 ...
- E-R图学习笔记
E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型.属性和联系的方法,用来描述现实世界的概念模型. 方法 编辑 E-R方法是“实体-联系方法”( ...
- Spring的一些资源
1.http://spring.io/ 2.http://projects.spring.io/spring-framework/
- NYOJ-1058 DFS部分求和
原题链接 本题思路:暴力深搜,具体见代码. #include <iostream> #include <stack> using namespace std; + ; int ...
- 191. Number of 1 Bits (Int; Bit)
Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...
- Lua面试题目
1.Lua的特性 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里. 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提 ...