Andndroid:ListView缓存机制及BaseAdapter

大家都知道listview的格式是一定的 而数据源确是多重多样的 这时候
就需要一种适配器来把数据源转换成listview要显示的格式 
baseAdapter就诞生了。

listview和gridView的显示和缓存机制


cache


BaseAdapter 
大家都知道屏幕的大小是有限的
可是listview中的数据却可能很多 所以手机不能一下子展示所有的数据 它只会加载屏幕上显示的数据 。 
如上图,当我们把屏幕往下滑动时 item1回收到recycler 而item8要显示在屏幕上
item8从recycler取出这样一个布局文件 并重新设置好item8要显示的数据 并设置要要显示的位置。 
总之一句话 需要才显示 显示完就被回收到缓存。在listview的适配器上
有这样一个方法

@Override  
public View getView(int position, View convertView, ViewGroup parent) {  
    // TODO Auto-generated method stub  
    return null;  
} 
  • 1
  • 2
  • 3
  • 4
  • 5

三种方式


下面我们通过一个实例 来比较adapter的三重境界孰强孰弱 
要实现的效果如下
 
BaseAdapter

activity_main.xml
[html] view plain copy print?在CODE上查看代码片派生到我的代码片
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical" >  
    <ListView   
        android:id="@+id/lv_listView"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        ></ListView>  

</LinearLayout>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
item.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="match_parent" >  

    <ImageView  
        android:id="@+id/iv_image"  
        android:layout_width="50dp"  
        android:layout_height="50dp"  
        android:layout_alignParentLeft="true"  
        android:src="@drawable/ic_launcher" />  

    <TextView  
        android:id="@+id/tv_nickName"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:layout_toRightOf="@id/iv_image"  
        android:gravity="center_horizontal"  
        android:textSize="20sp"  
        android:text="昵称" />  

    <TextView  
        android:id="@+id/tv_content"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:layout_toRightOf="@id/iv_image"  
        android:layout_below="@id/tv_nickName"  
        android:textSize="15sp"  
        android:text="内容" />  

</RelativeLayout>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

为了方便 ,我创建了一个myObject对象 用来封装item.xml要显示的数据

MyObject.class
package com.example.baseadapter;  

import android.widget.ImageView;  
import android.widget.TextView;  

public class MyObject {  
    private int imageViewId;  
    private String nickName;  
    private String content;  

    public MyObject(int imageViewId, String nickName, String content) {  
        this.imageViewId = imageViewId;  
        this.nickName = nickName;  
        this.content = content;  
    }  

    public String getNickName() {  
        return nickName;  
    }  

    public String getContent() {  
        return content;  
    }  

    public int getImageViewId() {  
        return imageViewId;  
    }  

}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

MainActivity.class

package com.example.baseadapter;  

import java.util.ArrayList;  
import java.util.List;  

import android.os.Bundle;  
import android.app.Activity;  
import android.view.Menu;  
import android.widget.ListView;  

public class MainActivity extends Activity {  
    private List<MyObject> list=new ArrayList<MyObject>();  
    private ListView listView;  
    private MyAdapter myAdapter;  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        listView=(ListView) findViewById(R.id.lv_listView);  
        for(int i=0;i<50;i++){  
            list.add(new MyObject(R.drawable.ic_launcher, "昵称"+i,   "内容"+i));  
        }  
        myAdapter=new MyAdapter(list, this);  
        listView.setAdapter(myAdapter);  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

自定义的adapter 
MyAdapter.class

package com.example.baseadapter;  

import java.util.List;  

import android.content.Context;  
import android.util.Log;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.ImageView;  
import android.widget.TextView;  

public class MyAdapter extends BaseAdapter {  

    private long sum = 0;  
    private List<MyObject> list;  
    private Context context;  

    public MyAdapter(List<MyObject> list, Context context) {  
        this.list = list;  
        this.context = context;  
    }  

    @Override  
    public int getCount() {  
        // TODO Auto-generated method stub  
        return list.size();  
    }  

    @Override  
    public Object getItem(int position) {  
        // TODO Auto-generated method stub  
        return list.get(position);  
    }  

    @Override  
    public long getItemId(int position) {  
        // TODO Auto-generated method stub  
        return position;  
    }  

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        // TODO Auto-generated method stub  
        // 第一种  
         long star = System.nanoTime();  
         View view=View.inflate(context, R.layout.item, null);  
         ImageView imageView =(ImageView) view.findViewById(R.id.iv_image);  
         TextView nickName=(TextView) view.findViewById(R.id.tv_nickName);  
         TextView content=(TextView) view.findViewById(R.id.tv_content);  
         MyObject myObject=list.get(position);  
         imageView.setBackgroundResource(myObject.getImageViewId());  
         nickName.setText(myObject.getNickName());  
         content.setText(myObject.getContent());  
         long end = System.nanoTime();  
         sum += end - star;  
         Log.d("main", "第一种" + sum);  
         return view;  
        // 第二种  
//      long star = System.nanoTime();//获取系统纳秒时间  
//      if (convertView == null) {  
//          convertView = View.inflate(context, R.layout.item, null);  
//      }  
//      ImageView imageView = (ImageView) convertView  
//              .findViewById(R.id.iv_image);  
//      TextView nickName = (TextView) convertView  
//              .findViewById(R.id.tv_nickName);  
//      TextView content = (TextView) convertView.findViewById(R.id.tv_content);  
//      MyObject myObject = list.get(position);  
//      imageView.setBackgroundResource(myObject.getImageViewId());  
//      nickName.setText(myObject.getNickName());  
//      content.setText(myObject.getContent());  
//      long end = System.nanoTime();  
//      sum += end - star;  
//      Log.d("main", "第二种" + sum);  
//      return convertView;  
        // 第三种  
        // long star = System.nanoTime();  
        // ViewHolder viewHolder;  
        // if (convertView == null) {  
        // viewHolder=new ViewHolder();  
        // convertView = View.inflate(context, R.layout.item, null);  
        // viewHolder.imageView = (ImageView) convertView  
        // .findViewById(R.id.iv_image);  
        // viewHolder.nickName = (TextView) convertView  
        // .findViewById(R.id.tv_nickName);  
        // viewHolder.content = (TextView) convertView  
        // .findViewById(R.id.tv_content);  
        // //通过setTag方式 使viewHolder和convertView绑定在一起  
        // convertView.setTag(viewHolder);  
        // }  
        // viewHolder=(ViewHolder) convertView.getTag();  
        // MyObject myObject = list.get(position);  
        // viewHolder.imageView.setBackgroundResource(myObject.getImageViewId());  
        // viewHolder.nickName.setText(myObject.getNickName());  
        // viewHolder.content.setText(myObject.getContent());  
        // long end = System.nanoTime();  
        // sum += end - star;  
        // Log.d("main", "第三种"+sum);  
        // return convertView;  
    }  

    // 避免重复的findViewById  
    class ViewHolder {  
        public ImageView imageView;  
        private TextView nickName;  
        private TextView content;  
    }  

}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

下面我们分析一下第一种 
前面已经说了,liseview具有缓存机制 可以将使用过的item放入缓冲池中,而在这里
每次调用getview方法的时候 我们都是创建新的view对象 并没有利用listview的缓存机制 
没有任何处理 ,效率及其低下 
而第二种 普通式是利用了getview方法中传入的contentview对象
并且加一个if判断

if (convertView == null) {  
    convertView = View.inflate(context, R.layout.item, null);  
}  
  • 1
  • 2
  • 3

虽然只是一个if判断 但是 通过这个判断 可以避免创建大量的contentview对象 节省了大量的时间
利用了ListView的缓存特性 如果没有缓存才创建新的view 对getview方法进行了非常好的优化
但这仅仅只算入门,因为findViewById依然会浪费大量的时间 所以我们称这种方法为普通式 
那么第三种境界就是对findViewById的优化了 把findViewById
也放入if判断语句中 就ok了 
我们需要创建一个内部类
里面有三个成员变量 都是我们item.xml文件中的三个控件

class ViewHolder {  
    public ImageView imageView;  
    private TextView nickName;  
    private TextView content;  
}  
  • 1
  • 2
  • 3
  • 4
  • 5

通过viewHolder.setTag()方法 把viewHolder和contentView关联在一起
然后通过getTag方法得到viewHolder 
这种方法不仅利用了listview的缓存,更通过viewHolder来实现显示视图的缓存,避免多次使用findViewById方法 
作为一个有情怀的程序员 这才是最好的写法~


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇