关闭

android--UI--listview使用和优化

460人阅读 评论(0) 收藏 举报
分类:

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打开

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:115428次
    • 积分:2018
    • 等级:
    • 排名:千里之外
    • 原创:88篇
    • 转载:4篇
    • 译文:0篇
    • 评论:19条
    最新评论