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

来源:互联网 发布:汉王人脸考勤机数据库 编辑:程序博客网 时间:2024/06/05 05:33

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
原创粉丝点击