温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

android ListView详解

发布时间:2020-07-10 14:09:04 来源:网络 阅读:413 作者:午饭123 栏目:移动开发

    在android开发中ListView是非常重要的控件。我自己也还是一个小白,把自己的学习经验分享出来,希望可以帮到初学Android的朋友们。这也是我第一次写博客,我尽量将结构处理的好一些,也说的易懂一些。如果写得不好或者有误,请指正见谅!

    

简介

    ListView特性是批量展示结构一样或者相似的信息并且可以滑动展示。ListView是一个组合控件,组合控件和普通控件的区别在于:

    普通控件:内容和控件是一起的。
    
组合控件:内容跟控件是分开的。


    所以使用ListView的时候要用到适配器,那什么是适配器呢,官方文档的解释是控件与数据之间的一个桥梁。如果不好理解,不要纠结,用多了自然就明白了。ListView作为一个整体的框架,而适配器则决定每一行上的内容是什么:


    ListView     框架

    适配器       内容


使用

    简单介绍过ListView之后,我们来说下ListView的使用。


    1、在Activity的布局文件中放入Listview,注意listview的高度要是match_parent 或者是固定值,这里不建议使用wrapcontent,因为这样会有requestLayout的操作,对性能有损耗。


    2、准备好listview的行布局文件listview_item,作为listview每一行的显示样式。


    3、准备listview的适配器,声明一个类继承BaseAdpater,实现四个方法:

       //这个方法决定了listview显示内容的行数

       public int getCount() 

       //决定listview每一行的布局以及内容,position代表是listview上面的行号。

       public View getView(int position, View convertView, ViewGroup parent)

       注意:·listview上的每一行要显示在界面上都必须调用getView()

             ·每一个已经消失在屏幕上的行,重新显示在界面都必须重新调用getView()

            ·如果getCount() 返回的结果为0的话,是不会调用getView()


    4、getView()中每一行的布局创建以及内容设置

               //获取行布局对象(通过解析行布局文件)

          LayoutInflater inflater = getLayoutInflater();//得到布局转换器

          View layout = inflater.inflate(R.layout.list_item, null);


        //通过布局对象查找它里面控件的索引 (一定要通过行布局对象查找)很多初学者在使用ListView的时候很容易报空指针错误,就是这个原因。

          TextView textView =(TextView)layout.findViewById(R.id.tv_list_item);


        //通过行号查找容器里面对应的内容

          String string = arrayList.get(position);


        //把内容设置到布局对象里面的控件对象上面

          textView.setText(string);


        //返回行布局对象(而不是里面某个控件)

          return layout;

 

    5、查找Listview控件对象

        ListView listView = (ListView) findViewById(R.id.listView1);


    

    6、创建一个适配器对象

          MyAdapter adapter = new MyAdapter();


    7、为listview配置适配器(如果没有配置,listview里面是没有内容的)

          listView.setAdapter(adapter)


    这里再说明一下,行布局为多个控件,就是之前创建的listview_item,每一行都是listview_item。还要注意的是每行数据都要封装到同一个对象当中,比如都是将数据设置到listview_item里的textview上,这里再重申一遍,每一个控件的索引都必须通过行布局对象去查找。(否则就为null,运行时会报空指针异常)。


优化    

    讲完ListView的使用后,讲一下ListView的优化。 

    1、复用行布局

    为什么要优化ListView呢,因为上面的写法,每一次getView()的时候都创建一个新的行布局对象,又因为Android的垃圾回收机制是不定时回收的,当数据比较多的时候,你上下滑动,ListView就不断的创建对象,轻则会造成卡顿,重则就内存溢出了。其实我们知道,如果屏幕上可以显示6行,我们准备7个布局对象就可以。如果不明白的童鞋可以想象一下,就像戏台上演行军并不需要那么多人,只要让前面走出戏台的人再从后面接上来就可以了。

    复用行布局:

    public View getView(int position, View convertView, ViewGroup parent) 

    {

      View layout = null;

    

      if(convertView == null)

      {

       LayoutInflater inflater = getLayoutInflater();//得到布局转换器

          layout = inflater.inflate(R.layout.list_item, null);

      }else

      {

       layout = convertView;

      }

    return layout;

    }

    说明: convertView用来保存已经创建并且消失在界面的那个行布局对象的索引。初始为null,当行布局对象消失的时候才有值


    2、减少查找次数

    基于复用行布局的基础上,如果每一次getView(),都要再去找行布局上的控件也是很麻烦的,因为既然是复用,之前肯定是已经找过了。这里的优化方法如下:

    声明一个类,类里面的成员变量即为 行布局里面的 控件类型   

   a、class ViewHolder

    {

    //将行布局内的控件申明为该类的成员变量

         ImageView p_w_picpathView;

         TextView title;

         TextView subTitle;

     }


   b、在getVIew中

        public View getView(int position, View convertView, ViewGroup parent) 

    {

      View layout = null;

      ViewHolder holder = null;

      if(convertView == null)

      {

       holder = new ViewHolder();

       LayoutInflater inflater = getLayoutInflater();//得到布局转换器

       layout = inflater.inflate(R.layout.list_item, null);

       holder.p_w_picpathView = (ImageView) layout.findViewById(R.id.iv_list);

       holder.title = (TextView) layout.findViewById(R.id.tv_list_item);

       holder.subTitle = (TextView) layout.findViewById(R.id.tv_list_sub);

       //标签(口袋)

       layout.setTag(holder);

      }else

      {

       layout = convertView;

       //如果convertView不为空,得到holder,然后得到行布局内控件的引用。

       holder = (ViewHolder) layout.getTag();

      }

    当然ListView的优化在实际的项目开发中在数据请求的过程中会有一些bug,这里以后再说明解决。


数据的更新

    //通知适配器内容发生改变,更新界面

      adapter.notifyDataSetChanged();


lisetview 行点击事件

    1、设置行点击事件

    listView.setOnItemClickListener(new OnItemClickListener() {

   @Override

   public void onItemClick(AdapterView parent, View view,

     int position, long id) {

    Log.e("onItemClick", "position:" + position);

   }

  });

    2、长按弹出选项菜单

   //为listview注册上下文菜单

    registerForContextMenu(listView);

   //长按事件

    listView.setOnItemLongClickListener(new OnItemLongClickListener() {

   @Override

    public boolean onItemLongClick(AdapterView parent, View view,

     int position, long id) {

    Log.e("onItemLongClick", "position:" + position);

    MainActivity.this.position = position;

    return false;   (返回false的时候事件还会向下传递,返回true就到此结束)

   }

  });

    当然还需重写onCreateContextMenu和onContextItemSelected方法。listvew长按弹出选项菜单还有另一种方法:   

    listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

    // @Override

    public void onCreateContextMenu(ContextMenu menu, View v,

    ContextMenuInfo menuInfo) {

    

    }

  });


总结

   好了,ListView就讲到这里了,当然要做出漂亮的listview还没那么简单,这些可能会在后面的博客中说道,希望这篇博客对大家有所帮助,谢谢!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI