• Android学习笔记(十一)——ListView的使用(下)


      //此系列博文是《第一行Android代码》的学习笔记,如有错漏,欢迎指正!

      ListView 这个控件比较复杂, 就是因为它有很多的细节可以优化,下面我们在试试提高它的运行效率:
    一、提高ListView的运行效率:
      目前我们ListView的运行效率是很低的, 因为在LetterAdapter的getView()方法中每次都将布局重新加载了一遍,当 ListView快速滚动的时候这就会成为性能的瓶颈。

      仔细观察的话,可以发现getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。

     1 @Override
     2     public View getView(int position, View convertView, ViewGroup parent) {
     3         Letter letter = getItem(position); // 获取当前项的Letter实例
     4         View view;
     5         if (convertView == null) {
     6             view = LayoutInflater.from(getContext()).inflate(resourceId, null);
     7         } else {
     8             view = convertView;
     9         }
    10         ImageView letterImage = (ImageView) view.findViewById(R.id.letter_image);
    11         TextView letterName = (TextView) view.findViewById(R.id.letter_name);
    12         letterImage.setImageResource(letter.getImageId());
    13         letterName.setText(letter.getName());
    14         return view;
    15     }

      可以看到,现在我们在 getView()方法中进行了判断,如果 convertView 为空,则使用LayoutInflater 去加载布局,如果不为空则直接对 convertView 进行重用。这样就大大提高了ListView的运行效率,在快速滚动的时候也可以表现出更好的性能。此外,我们还可以继续优化:

     1 public class LetterAdapter extends ArrayAdapter<Letter> {
     2     private int resourceId;
     3     public LetterAdapter(Context context, int textViewResourceId, List<Letter> objects) {
     4         super(context, textViewResourceId, objects);
     5         resourceId = textViewResourceId;
     6     }
     7     @Override
     8     public View getView(int position, View convertView, ViewGroup parent) {
     9         Letter letter = getItem(position); // 获取当前项的Letter实例
    10         View view;
    11         ViewHolder viewHolder;
    12         if (convertView == null) {
    13             view = LayoutInflater.from(getContext()).inflate(resourceId, null);
    14             viewHolder = new ViewHolder();
    15             viewHolder.letterImage = (ImageView) view.findViewById
    16                     (R.id.letter_image);
    17             viewHolder.letterName = (TextView) view.findViewById
    18                     (R.id.letter_name);
    19             view.setTag(viewHolder); //  将ViewHolder 存储在View
    20         } else {
    21             view = convertView;
    22             viewHolder = (ViewHolder) view.getTag(); //  重新获取ViewHolder
    23         }
    24         viewHolder.letterImage.setImageResource(letter.getImageId());
    25         viewHolder.letterName.setText(letter.getName());
    26         return view;
    27     }
    28 
    29     class ViewHolder {
    30         ImageView letterImage;
    31         TextView letterName;
    32     }
    33 }
    View Code

      我们新增了一个内部类 ViewHolder,用于对控件的实例进行缓存。当 convertView为空的时候, 创建一个 ViewHolder 对象, 并将控件的实例都存放在 ViewHolder里, 然后调用 View的 setTag()方法,将 ViewHolder 对象存储在 View 中。当 convertView 不为空的时候则调用View的 getTag()方法, 把 ViewHolder重新取出。 这样所有控件的实例都缓存在了 ViewHolder里,就没有必要每次都用findViewById()方法来获取控件实例了。

    二、ListView的点击事件:
      为ListView添加点击事件只需在主活动中为ListView注册监听器即可:

     1  @Override
     2     protected void onCreate(Bundle savedInstanceState) {
     3         super.onCreate(savedInstanceState);
     4         setContentView(R.layout.activity_main);
     5         initLetters(); //  初始化数据
     6         LetterAdapter adapter = new LetterAdapter(MainActivity.this,
     7                 R.layout.letter_item, letterList);
     8         ListView listView = (ListView) findViewById(R.id.list_view);
     9         listView.setAdapter(adapter);
    10         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    11             @Override
    12             public void onItemClick(AdapterView<?> parent, View view,
    13                                     int position, long id) {
    14                 Letter letter = letterList.get(position);
    15                 Toast.makeText(MainActivity.this, letter.getName(),
    16                         Toast.LENGTH_SHORT).show();
    17             }
    18         });
    19     }

      可以看到,我们使用了 setOnItemClickListener()方法来为 ListView 注册了一个监听器,当用户点击了 ListView 中的任何一个子项时就会回调 onItemClick()方法, 在这个方法中可以通过 position 参数判断出用户点击的是哪一个子项,然后获取到相应的水果,并通过 Toast将字母显示出来。

      //End.

  • 相关阅读:
    C语言scanf函数转换说明表及其修饰符表
    C语言printf函数转换说明表及其修饰符表
    JAVA中this和super用法
    JAVA构造器,重载与重写
    初步学习JAVA面向对象初步认识及面向对象内存分析图举例说明
    webpack4.0报WARNING in configuration警告
    chrome开发者工具--使用 Network 面板测量您的网站网络性能。
    随笔记录--Array类型
    PXC(percona xtradb cluster)新加节点避免SST的方法
    pt-online-schema-change原理解析
  • 原文地址:https://www.cnblogs.com/Vincent-Bryan/p/5389472.html
Copyright © 2020-2023  润新知