1.ListView的基本操作
ListView是用来显示大量数据的,数据可以先储存在数组中,数据可以是从网上下载的,也可以是数据库中的数据,在数组中数据不能直接显示在界面上,可使用配适器,这里用ArrayAdapter做例子,将数据放进每一个子布局中,最后将配适器创建好的对象传递给ListView
(1)使用系统的布局,只有TextView,可以简单的显示一段文本
private String[] arr = {"标题一","标题二","标题三"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,arr);
ListView listView = findViewById(R.id.list_item);
listView.setAdapter(arrayAdapter);
}
(2)自定义ListView
- 定义类,作为配适器的泛型
- 重写子布局,将类中的数据存放
- 重新定义配适器,可以将数据传给子布局,要重写getView方法
定义myBean类,成员变量是图片和文字
public class myBean {
private String text;
private int ImageId;
public myBean(String text,int imageid) {
this.ImageId = imageid;
this.text = text;
}
public int getImageId() {
return ImageId;
}
public String getText() {
return text;
}
public void setImageId(int imageId) {
ImageId = imageId;
}
public void setText(String text) {
this.text = text;
}
}
重写每个子布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_margin="5dp"
/>
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="15dp"
android:layout_gravity="center_vertical"
android:layout_margin="20dp"
/>
</LinearLayout>
重写配适器:在继承之后需要写出构造函数,并将子布局记录下来,用于LayoutInflater.from(getContext()).inflate(Imageid,parent,false)函数,【LayoutInflater是从res/layout找xml文件,getContext()是得到当前布局的环境,
LayoutInflater类inflate方法有两种,一种是带3个参数的:inflate(int resource, ViewGroup root, boolean attachToRoot)
resource:需要加载布局资源文件的id,意思是需要将这个布局文件中加载到Activity中来操作。
root:需要附加到resource资源文件的根控件,就是inflate()会返回一个View对象,如果第三个参数attachToRoot为true,就将这个root作为根对象返回,否则仅仅将这个root对象的LayoutParams宽高参数属性附加到resource对象的根布局对象上,也就是布局文件resource的最外层的View上,比如是一个LinearLayout或者其它的Layout对象。如果没有根控件,就写null
nullattachToRoot:是否将root附加到布局文件的根视图上(可以写true或false)
另一种带2个参数的,也就是少了boolean attachToRoot参数的】
public class myAdapter extends ArrayAdapter<myBean> {
private int Imageid;
public myAdapter(Context context, int imageid, List<myBean> list) {
super(context,imageid,list);
Imageid = imageid;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
myBean myBean = getItem(position);
View view = LayoutInflater.from(getContext()).inflate(Imageid,parent,false);
ImageView imageView = view.findViewById(R.id.image);
TextView textView = view.findViewById(R.id.text_view);
imageView.setImageResource(myBean.getImageId());
textView.setText(myBean.getText());
return view;
}
}
- 关于重写getView()方法,首先通过位置获取myBean对象,将对象中的成员变量与布局中的子控件对应起来
最后进行与使用系统布局相同的操作即可
private List<myBean> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
myAdapter myAdapter = new myAdapter(MainActivity.this,R.layout.activity_item,list);
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(myAdapter);
}
public List<myBean> init() {
for (int i = 0;i < 30;i++) {
myBean myBean = new myBean("项目一",R.drawable.f);
list.add(myBean);
}
return list;
}
2.提升ListView的运行效率
(1)getView()中每次都将布局重新加载,当List View快速滚动时,这可能会成为性能的瓶颈
public View getView(int position, View convertView, ViewGroup parent) {
myBean myBean = getItem(position);
View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(Imageid,parent,false);
}else {
view = convertView;
}
ImageView imageView = view.findViewById(R.id.image);
TextView textView = view.findViewById(R.id.text_view);
imageView.setImageResource(myBean.getImageId());
textView.setText(myBean.getText());
return view;
}
(2)findViewById这个方法是从ViewGroup的子View里面循环遍历找id与给出的ID相同的子View,还是比较耗时的,源码如下:
/**ViewGroup的FindViewByID源码*/
/**
* {@hide}
*/
@Override
protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
return (T) this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return (T) v;
}
}
}
return null;
}
我们使用ViewHolder()去缓存
public View getView(int position, View convertView, ViewGroup parent) {
myBean myBean = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(Imageid,parent,false);
viewHolder = new ViewHolder();
viewHolder.imageView = view.findViewById(R.id.image);
viewHolder.textView = view.findViewById(R.id.text_view);
view.setTag(viewHolder);//将ViewHolder存储在View中
}else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.imageView.setImageResource(myBean.getImageId());
viewHolder.textView.setText(myBean.getText());
return view;
}
class ViewHolder {
ImageView imageView;
TextView textView;
}