004 Andriod ListView组件的使用

1.介绍

总结:ListView 是一个可以以垂直滚动的方式展示条目内容的一个列表,条目的内容来自于ListAdapter(适配器)。

2.操作步骤

3.ListView中convertView和ViewHolder的工作原理

Android中有个叫做Recycler(反复循环器)的构件,下图是它的工作原理:

 

 

(1)如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中
(2)当item1滚出屏幕,并且一个新的项目从屏幕地段上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1.你只需要设定新的数据返回convertView,不必重新创建一个视图。这样直接使用convertView从而减少了很不不必要view的创建

 

4.典型ListView数据适配器方法分析

示例代码:

(1)xml布局文件

复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="6dp"
    android:layout_centerVertical="true">

    <TextView
        android:layout_marginTop="10dp"
        android:id="@+id/tv_phone_number"
        android:text="拦截号码"
        android:textSize="18dp"
        android:textColor="#000000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tv_function_type"
        android:text="拦截类型"
        android:textSize="18dp"
        android:layout_below="@+id/tv_phone_number"
        android:layout_marginTop="10dp"
        android:textColor="#000000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <!--<ImageView-->
        <!--android:layout_alignParentRight="true"-->
        <!--android:background="@drawable/selector_black_call_delete1_bg"-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content" />-->

    <!--android:background="@drawable/selector_black_call_delete1_bg"-->
    <ImageView
        android:id="@+id/iv_black_call_delete"
        android:layout_alignParentRight="true"
        android:background="@drawable/selector_black_call_delete1_bg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>
复制代码

(2)java后台代码:

复制代码
/**
     * listview的数据适配器
     */
    private class MyAdapter extends BaseAdapter {
        //getCount决定了listview一共有多少个item
        @Override
        public int getCount() {
            return blackCallList.size();
        }

        //获得相应数据集合中特定位置的数据项
        @Override
        public Object getItem(int position) {
            return blackCallList.get(position);
        }

        //返回该postion对应item的id
        @Override
        public long getItemId(int position) {
            return position;
        }

        //getView()返回了每个item项所显示的view
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            //复用convertView,并减少了findViewById的次数
            ViewHolder holder=null;
            //1.convertView为空,代表当前的条目是首次构建,需要查找控件,查找到的控件在后续的条目中可以去做复用
            if(convertView==null){
                convertView=View.inflate(getApplicationContext(), R.layout.listview_black_list_call_item, null);
                //2.创建一个ViewHolder对象,去存储所找到的控件
                holder=new ViewHolder();
                holder.tv_phone_number=convertView.findViewById(R.id.tv_phone_number);
                holder.tv_function_type=convertView.findViewById(R.id.tv_function_type);
                holder.iv_black_call_delete=convertView.findViewById(R.id.iv_black_call_delete);
                //3.存储当前的ViewHolder对象
                convertView.setTag(holder);
            }else {
                //4.复用convertView中存储的ViewHolder对象
                holder= (ViewHolder) convertView.getTag();
            }

            holder.tv_phone_number.setText(blackCallList.get(position).getPhoneNumber());
            holder.tv_function_type.setText(blackCallList.get(position).getFunctionType());

            //给图片imageview绑定点击事件
            holder.iv_black_call_delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    BlackListCallDBUtil.deleteOneRecord(blackCallList.get(position).getPhoneNumber(),blackCallList.get(position).getFunctionType());
                    initData(); //重新显示列表数据
                }
            });
            return convertView;
        }

        private class ViewHolder {
            public TextView tv_phone_number;
            public TextView tv_function_type;
            public ImageView iv_black_call_delete;
        }
    }
复制代码

(1)getCount()方法:决定了listview一共有多少个item(条目)

(2)getItem()方法:获得相应数据集合中特定位置的数据项

常用于:listview的点击事件(例如setOnItemSelectedListener),方便地调用来获取获取当前行数据

(3)getItemId()方法:返回该postion对应item的id

(4)getView()方法:返回了每个item项所要显示的view

5.内存溢出问题(快速拖到条目)

利用getView(int i, View view, ViewGroup viewGroup) 方法的第二个参数,回收已经隐藏的组件

6.listView 显示数据的原理

mvc模式:

<1>javaweb中

m:mode 数据 ;v:view 视图 jsp ;c:controller servlet

<2>Android 

m:mode 数据(javabean)

v:view 视图 组件

c:adapter (适配器)

注意:无论是哪种Adapter,其作用都是把数据展示到listview中

7.xml布局

<1>activity_main.xml布局

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/lv_message"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ListView>

</LinearLayout>
复制代码

注意:ListView的高度必须设置为  android:layout_height="match_parent"

<2>item_show.xml布局

复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/imageView"
        android:ellipsize="end"
        android:singleLine="true"
        android:text="掘金115-105雷霆,默里27+5+9,约基奇23+16,威少27+9+9,乔治25+9"
        android:textColor="#000000"
        android:textSize="20dp" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_title"
        android:layout_toRightOf="@+id/imageView"
        android:ellipsize="end"
        android:maxLines="2"
        android:textColor="#6D6E72"
        android:text="虎扑3月30日讯,雷霆坐镇主场迎来了掘金的挑战。首节比赛,约基奇展现了自己在内线的统治力,4投4中单节砍下10分7篮板2助攻。于此同时,还让对位的雷霆中锋亚当斯在首节数据挂零。凭借约基奇的出色表现,掘金在首节就取得了33-29的领先。次节比赛,掘金攻势依然凶猛,开场一波7-0的小高潮立刻将分差拉大到了两位数。但首节表现低迷的亚当斯终于迎来了复苏,5投全中砍下10分,帮助雷霆奋起直追,最终雷霆成功将分差再次缩小到了4分,两队的比分定格在了56-52。"
        android:textSize="15dp" />
</RelativeLayout>
复制代码

注意:采用相对布局,若图片不能加载,设置图片来源为 android:src="@mipmap/ic_launcher"

8.java后台

复制代码
package com.example.lucky.test53listview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    ListView lv_message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv_message=findViewById(R.id.lv_message);
        lv_message.setAdapter(new MyListAdapter());
    }

    //ListView的数据适配器
    public class MyListAdapter extends BaseAdapter{

        //设置一共需要显示的数据条数
        @Override
        public int getCount() {
            return 60;
        }

        //返回position位置对应的对象
        @Override
        public Object getItem(int i) {
            return null;
        }

        //返回position位置对应的id
        @Override
        public long getItemId(int i) {
            return 0;
        }

        //获取一个view,用来显示ListView的数据,会作为ListView的一个条目出现
        //参数2为历史缓存对象(页面一次会显示的textView对象都是新创建的,当用户滑动列表时,后面显示textview 是复用前面的view)
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            View viewShow;
            if(view==null){
                //创建新的view对象,可以通过打气筒(View.inflate())把一个布局资源转换成一个view对象
                viewShow=View.inflate(getApplicationContext(),R.layout.item_show,null);
                System.out.println("创建新的view对象"+i);
            }else {
                System.out.println("复用历史缓存对象"+i);
                viewShow= view;
            }
            return viewShow;
        }
    }
}
复制代码

9.效果图

posted @   雨后观山色  阅读(227)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示