android--ListView

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值