BaseAdapter中重写getview的心得以及发现convertView回收的机制

转载自:http://blog.csdn.net/pkxiuluo01/article/details/7380974

以前一直在用BaseAdapter,对于其中的getview方法的重写一直不太清楚。今天终于得以有空来探究它的详细机制。
下面先讲讲我遇到的几个问题:
一.View getview(int position, View convertview, ViewGroup parent )中的第二个参数是什么含义;
二.View的SetTag和getTag方法的用途;
先来解决第一个问题:
android SDK中这样讲参数 convertview :
the old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using.

If it is not possible to convert this view to display the correct data, this method can create a new view.
翻译:
如果可以的话,这是旧View(这里不便翻译有的人翻成视图)的重用。 建议:在用之前,你应该检查这个View是
不是非空,是不是一个合适的类型。
如果不可能让这个VIew去显示一个恰当的数据,这个方法会创建一个新的View。

如果我们要做的是一个ListView,在手机上显示的只有那么几条Item,而整个ListView可能有很长,可能是100条
甚至是上万条,总不能让这么多条Item都驻留在内存中,所以android为你准备了一套机制,就是Recycler(反复循
环器),他的具体工作原理可以到 http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html去看。
但是有些地方他没有讲清,所以我再讲一下。先把代码贴出来
布局文件main.xml

[java] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <ListView
  7. android:id="@+id/result"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. android:cacheColorHint="#00000000" >
  11. </ListView>
  12. </LinearLayout>

此处注意ListView的android:layout_height属性值为"fill_paternt",如果为“wrap_content"将会是另一种情况

adapter的代码ListViewAdapter.java 

[java] view plaincopy

  1. class ListViewAdapter extends BaseAdapter
  2. {
  3. private Context mContext;
  4. int i=0;
  5. public ListViewAdapter (Context context)
  6. {
  7. this.mContext=context;
  8. }
  9. @Override
  10. public int getCount()
  11. {
  12. return 30;
  13. }
  14. @Override
  15. public Object getItem(int position)
  16. {
  17. return position;
  18. }
  19. @Override
  20. public long getItemId(int position)
  21. {
  22. return 0;
  23. }
  24. @Override
  25. public View getView(int position, View convertView, ViewGroup parent)
  26. {
  27. System.out.println("getView " + position + " " + convertView);//调试语句
  28. Holder holder;
  29. if(null==convertView)
  30. {
  31. holder=new Holder();
  32. convertView=LayoutInflater.from(mContext).inflate(R.layout.textview, null); //mContext指的是调用的Activtty
  33. holder.textView=(TextView)convertView.findViewById(R.id.textview);
  34. convertView.setTag(holder);
  35. }
  36. else
  37. {
  38. holder=(Holder)convertView.getTag();
  39. }
  40. holder.textView.setText("position: "+position);
  41. return convertView;
  42. }
  43. class Holder
  44. {
  45. public TextView textView;
  46. }
  47. }

运行程序之后发现屏幕上显示出的Item的convertview都为空,向下滑动新产生的Item的convetview都不为空。到此为止和上面链接中讲的是一致的,但是如果设置ListView的android:layout_height属性值为“wrap_content

之后,发现只有第一个Item的convertview为null其他的不为空。

虽然两种设置不同,结果也不同,但是convertview的机制没有变。

其实到此为止我们可以总结出convertview的机制了,就是在初始显示的时候,每次显示一个item都调用一次getview方法但是每次调用的时候covertview为空(因为还没有旧的view),当显示完了之后。如果屏幕移动了之后,并且导致有些Item(也可以说是view)跑到屏幕外面,此时如果还有新的item需要产生,则这些item显示时调用的getview方法中的convertview参数就不是null,而是那些移出屏幕的view(旧view),我们所要做的就是将需要显示的item填充到这些回收的view(旧view)中去,最后注意convertview为null的不仅仅是初始显示的那些item,还有一些是已经开始移入屏幕但是还没有view被回收的那些item。

最终我们用亲手写的代码实现了Recycler(反复循环器).

 

第二个问题其实应该在第一个问题中嵌套来讲,但是为了思路清晰我分开了:

view的setTag和getTag方法其实很简单,在实际编写代码的时候一个view不仅仅是为了显示一些字符串、图片,有时我们还需要他们携带一些其他的数据以便我们对该view的识别或者其他操作。于是android 的设计者们就创造了setTag(Object)方法来存放一些数据和view绑定,我们可以理解为这个是view 的标签也可以理解为view 作为一个容器存放了一些数据。而这些数据我们也可以通过getTag() 方法来取出来。

到这里setTag和getTag大家应该已经明白了。再回到上面的话题,我们通过convertview的setTag方法和getTag方法来将我们要显示的数据来绑定在convertview上。如果convertview 是第一次展示我们就创建新的Holder对象与之绑定,并在最后通过return convertview 返回,去显示;如果convertview 是回收来的那么我们就不必创建新的holder对象,只需要把原来的绑定的holder取出加上新的数据就行了。

附:文中提到的未介绍透彻的另一个帖子:

http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html

ListView中getView的原理+如何在ListView中放置多个item

工作原理:

  1. ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
  2. 一个新的视图被返回并显示

如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!

实际上Android为你缓存了视图。

Android中有个叫做Recycler的构件,下图是他的工作原理:

  1. 如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。
  2. ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。
  3. 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。

请看下面的示例代码,这里在getView中使用了System.out进行输出


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

public class MultipleItemsList extends ListActivity {

 

    private MyCustomAdapter mAdapter;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mAdapter = new MyCustomAdapter();

        for (int i = 0; i < 50; i++) {

            mAdapter.addItem("item " + i);

        }

        setListAdapter(mAdapter);

    }

 

    private class MyCustomAdapter extends BaseAdapter {

 

        private ArrayList mData = new ArrayList();

        private LayoutInflater mInflater;

 

        public MyCustomAdapter() {

            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        }

 

        public void addItem(final String item) {

            mData.add(item);

            notifyDataSetChanged();

        }

 

        @Override

        public int getCount() {

            return mData.size();

        }

 

        @Override

        public String getItem(int position) {

            return mData.get(position);

        }

 

        @Override

        public long getItemId(int position) {

            return position;

        }

 

        @Override

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

            System.out.println("getView " + position + " " + convertView);

            ViewHolder holder = null;

            if (convertView == null) {

                convertView = mInflater.inflate(R.layout.item1, null);

                holder = new ViewHolder();

                holder.textView = (TextView)convertView.findViewById(R.id.text);

                convertView.setTag(holder);

            } else {

                holder = (ViewHolder)convertView.getTag();

            }

            holder.textView.setText(mData.get(position));

            return convertView;

        }

 

    }

 

    public static class ViewHolder {

        public TextView textView;

    }

}

执行程序,然后在Logcat中查看日志

getView 被调用 9 次 ,convertView 对于所有的可见项目是空值(如下)

02-05 13:47:32.559: INFO/System.out(947): getView 0 null

02-05 13:47:32.570: INFO/System.out(947): getView 1 null

02-05 13:47:32.589: INFO/System.out(947): getView 2 null

02-05 13:47:32.599: INFO/System.out(947): getView 3 null

02-05 13:47:32.619: INFO/System.out(947): getView 4 null

02-05 13:47:32.629: INFO/System.out(947): getView 5 null

02-05 13:47:32.708: INFO/System.out(947): getView 6 null

02-05 13:47:32.719: INFO/System.out(947): getView 7 null

02-05 13:47:32.729: INFO/System.out(947): getView 8 null

然后稍微向下滚动List,直到item10出现:

convertView仍然是空值,因为recycler中没有视图(item1的边缘仍然可见,在顶端)

02-05 13:48:25.169: INFO/System.out(947): getView 9 null

再滚动List

convertView不是空值了!item1离开屏幕到Recycler中去了,然后item11被创建

02-05 13:48:42.879: INFO/System.out(947): getView 10 android.widget.LinearLayout@437430f8

再滚动:

02-05 14:01:31.069: INFO/System.out(947): getView 11 android.widget.LinearLayout@437447d0

02-05 14:01:31.142: INFO/System.out(947): getView 12 android.widget.LinearLayout@43744ff8

02-05 14:01:31.279: INFO/System.out(947): getView 13 android.widget.LinearLayout@43743fa8

02-05 14:01:31.350: INFO/System.out(947): getView 14 android.widget.LinearLayout@43745820

02-05 14:01:31.429: INFO/System.out(947): getView 15 android.widget.LinearLayout@43746048

02-05 14:01:31.550: INFO/System.out(947): getView 16 android.widget.LinearLayout@43746870

02-05 14:01:31.669: INFO/System.out(947): getView 17 android.widget.LinearLayout@43747098

02-05 14:01:31.839: INFO/System.out(947): getView 18 android.widget.LinearLayout@437478c0

02-05 14:03:30.900: INFO/System.out(947): getView 19 android.widget.LinearLayout@43748df0

02-05 14:03:32.069: INFO/System.out(947): getView 20 android.widget.LinearLayout@437430f8

convertView 如我们所期待的非空了,在item11离开屏幕之后,它的视图(@437430f8)作为convertView容纳item21了

不同的项目布局(item layout)

我们再举一个稍微复杂的例子,在上例的list中加入一些分隔线

你需要做这些:

  1. 重(@Override)写 getViewTypeCount() – 返回你有多少个不同的布局
  2. 重写 getItemViewType(int) – 由position返回view type id
  3. 根据view item的类型,在getView中创建正确的convertView

以下是代码:


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

public class MultipleItemsList extends ListActivity {

 

    private MyCustomAdapter mAdapter;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mAdapter = new MyCustomAdapter();

        for (int i = 1; i < 50; i++) {

            mAdapter.addItem("item " + i);

            if (i % 4 == 0) {

                mAdapter.addSeparatorItem("separator " + i);

            }

        }

        setListAdapter(mAdapter);

    }

 

    private class MyCustomAdapter extends BaseAdapter {

 

        private static final int TYPE_ITEM = 0;

        private static final int TYPE_SEPARATOR = 1;

        private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

 

        private ArrayList mData = new ArrayList();

        private LayoutInflater mInflater;

 

        private TreeSet mSeparatorsSet = new TreeSet();

 

        public MyCustomAdapter() {

            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        }

 

        public void addItem(final String item) {

            mData.add(item);

            notifyDataSetChanged();

        }

 

        public void addSeparatorItem(final String item) {

            mData.add(item);

            // save separator position

            mSeparatorsSet.add(mData.size() - 1);

            notifyDataSetChanged();

        }

 

        @Override

        public int getItemViewType(int position) {

            return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;

        }

 

        @Override

        public int getViewTypeCount() {

            return TYPE_MAX_COUNT;

        }

 

        @Override

        public int getCount() {

            return mData.size();

        }

 

        @Override

        public String getItem(int position) {

            return mData.get(position);

        }

 

        @Override

        public long getItemId(int position) {

            return position;

        }

 

        @Override

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

            ViewHolder holder = null;

            int type = getItemViewType(position);

            System.out.println("getView " + position + " " + convertView + " type = " + type);

            if (convertView == null) {

                holder = new ViewHolder();

                switch (type) {

                    case TYPE_ITEM:

                        convertView = mInflater.inflate(R.layout.item1, null);

                        holder.textView = (TextView)convertView.findViewById(R.id.text);

                        break;

                    case TYPE_SEPARATOR:

                        convertView = mInflater.inflate(R.layout.item2, null);

                        holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);

                        break;

                }

                convertView.setTag(holder);

            } else {

                holder = (ViewHolder)convertView.getTag();

            }

            holder.textView.setText(mData.get(position));

            return convertView;

        }

 

    }

 

    public static class ViewHolder {

        public TextView textView;

    }

}

运行程序,你会看到每4个item一个分割线

看看日志,无异常,所有的convertView都是空的

02-05 15:19:03.080: INFO/System.out(1035): getView 0 null type = 0

02-05 15:19:03.112: INFO/System.out(1035): getView 1 null type = 0

02-05 15:19:03.130: INFO/System.out(1035): getView 2 null type = 0

02-05 15:19:03.141: INFO/System.out(1035): getView 3 null type = 0

02-05 15:19:03.160: INFO/System.out(1035): getView 4 null type = 1

02-05 15:19:03.170: INFO/System.out(1035): getView 5 null type = 0

02-05 15:19:03.180: INFO/System.out(1035): getView 6 null type = 0

02-05 15:19:03.190: INFO/System.out(1035): getView 7 null type = 0

02-05 15:19:03.210: INFO/System.out(1035): getView 8 null type = 0

02-05 15:19:03.210: INFO/System.out(1035): getView 9 null type = 1

滚动list:

02-05 15:19:54.160: INFO/System.out(1035): getView 10 null type = 0

02-05 15:19:57.440: INFO/System.out(1035): getView 11 android.widget.LinearLayout@43744528 type = 0

02-05 15:20:01.310: INFO/System.out(1035): getView 12 android.widget.LinearLayout@43744eb0 type = 0

02-05 15:20:01.880: INFO/System.out(1035): getView 13 android.widget.LinearLayout@437456d8 type = 0

02-05 15:20:02.869: INFO/System.out(1035): getView 14 null type = 1

02-05 15:20:06.489: INFO/System.out(1035): getView 15 android.widget.LinearLayout@43745f00 type = 0

02-05 15:20:07.749: INFO/System.out(1035): getView 16 android.widget.LinearLayout@43747170 type = 0

02-05 15:20:10.250: INFO/System.out(1035): getView 17 android.widget.LinearLayout@43747998 type = 0

02-05 15:20:11.661: INFO/System.out(1035): getView 18 android.widget.LinearLayout@437481c0 type = 0

02-05 15:20:13.180: INFO/System.out(1035): getView 19 android.widget.LinearLayout@437468a0 type = 1

02-05 15:20:16.900: INFO/System.out(1035): getView 20 android.widget.LinearLayout@437489e8 type = 0

02-05 15:20:25.690: INFO/System.out(1035): getView 21 android.widget.LinearLayout@4374a8d8 type = 0

convertView对于分割线是空的,直到第一个分割线可见,当其离开屏幕,视图去到Recycler并且convertView开始起作用。

本文翻译自http://android.amberfog.com/?p=296

附2:上文的英文原文

http://android.amberfog.com/?p=296

ListView and Adapter Basics

How it works:

  1. ListView asks adapter “give me a view” (getView) for each item of the list
  2. A new View is returned and displayed

Next question – what if we have one billion items? Create new view for each item? The answer is NO:-) Android caches views for you.

There’s a component in Android called “Recycler”. I drawed a picture based on Romain Guy presentation at Google IO ’09.

  1. If you have 1 billion items – there are only visible items in the memory + view in recycler.
  2. ListView asks for a view type1 first time (getView) x visible items. convertView is null in getView – you create new view of type1 and return it.
  3. ListView asks for a view type1 when one item1 is outside of the window and new item the same type is comming from the bottom. convertView is not null = item1. You should just set new data and return convertView back. No need to create view again.

Let’s write a simple code and put System.out to the getView:

public class MultipleItemsList extends ListActivity {
 
    private MyCustomAdapter mAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 0; i < 50; i++) {
            mAdapter.addItem("item " + i);
        }
        setListAdapter(mAdapter);
    }
 
    private class MyCustomAdapter extends BaseAdapter {
 
        private ArrayList mData = new ArrayList();
        private LayoutInflater mInflater;
 
        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }
 
        @Override
        public int getCount() {
            return mData.size();
        }
 
        @Override
        public String getItem(int position) {
            return mData.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("getView " + position + " " + convertView);
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.item1, null);
                holder = new ViewHolder();
                holder.textView = (TextView)convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }
 
    }
 
    public static class ViewHolder {
        public TextView textView;
    }
}

Run the program and see what happens:

getView was called 9 times. convertView is null for all visible items

02-05 13:47:32.559: INFO/System.out(947): getView 0 null
02-05 13:47:32.570: INFO/System.out(947): getView 1 null
02-05 13:47:32.589: INFO/System.out(947): getView 2 null
02-05 13:47:32.599: INFO/System.out(947): getView 3 null
02-05 13:47:32.619: INFO/System.out(947): getView 4 null
02-05 13:47:32.629: INFO/System.out(947): getView 5 null
02-05 13:47:32.708: INFO/System.out(947): getView 6 null
02-05 13:47:32.719: INFO/System.out(947): getView 7 null
02-05 13:47:32.729: INFO/System.out(947): getView 8 null

Then scroll the list slightly down (until item 10 appears):

convertView is still null because there is still no view in the recycler (border of item1 is still visible at the top:))

02-05 13:48:25.169: INFO/System.out(947): getView 9 null

Let’s scroll list a little more:

Bingo! convertView is not null: item1 goes off the screen directly to the Recycler and item11 is created based on item1.

02-05 13:48:42.879: INFO/System.out(947): getView 10 [email protected]

scroll more just to check what hapens:

02-05 14:01:31.069: INFO/System.out(947): getView 11 [email protected]
02-05 14:01:31.142: INFO/System.out(947): getView 12 [email protected]
02-05 14:01:31.279: INFO/System.out(947): getView 13 [email protected]
02-05 14:01:31.350: INFO/System.out(947): getView 14 [email protected]
02-05 14:01:31.429: INFO/System.out(947): getView 15 [email protected]
02-05 14:01:31.550: INFO/System.out(947): getView 16 [email protected]
02-05 14:01:31.669: INFO/System.out(947): getView 17 [email protected]
02-05 14:01:31.839: INFO/System.out(947): getView 18 [email protected]
02-05 14:03:30.900: INFO/System.out(947): getView 19 [email protected]
02-05 14:03:32.069: INFO/System.out(947): getView 20 [email protected]

convertView is not null as we expected. After item11 goes off the screen, it view (@437430f8) comes as convertView for item 21. simple.

Different list items’ layouts

Let’s move to the “more complicated” example. How about to add separator somewhere to the list.

You should do the following:

  1. Override getViewTypeCount() – return how many different view layouts you have
  2. Override getItemViewType(int) – return correct view type id by position
  3. Create correct convertView (depending on view item type) in getView

Simple, isn’t it? Code snippet:

public class MultipleItemsList extends ListActivity {
 
    private MyCustomAdapter mAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new MyCustomAdapter();
        for (int i = 1; i < 50; i++) {
            mAdapter.addItem("item " + i);
            if (i % 4 == 0) {
                mAdapter.addSeparatorItem("separator " + i);
            }
        }
        setListAdapter(mAdapter);
    }
 
    private class MyCustomAdapter extends BaseAdapter {
 
        private static final int TYPE_ITEM = 0;
        private static final int TYPE_SEPARATOR = 1;
        private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
 
        private ArrayList mData = new ArrayList();
        private LayoutInflater mInflater;
 
        private TreeSet mSeparatorsSet = new TreeSet();
 
        public MyCustomAdapter() {
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        public void addItem(final String item) {
            mData.add(item);
            notifyDataSetChanged();
        }
 
        public void addSeparatorItem(final String item) {
            mData.add(item);
            // save separator position
            mSeparatorsSet.add(mData.size() - 1);
            notifyDataSetChanged();
        }
 
        @Override
        public int getItemViewType(int position) {
            return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
        }
 
        @Override
        public int getViewTypeCount() {
            return TYPE_MAX_COUNT;
        }
 
        @Override
        public int getCount() {
            return mData.size();
        }
 
        @Override
        public String getItem(int position) {
            return mData.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            int type = getItemViewType(position);
            System.out.println("getView " + position + " " + convertView + " type = " + type);
            if (convertView == null) {
                holder = new ViewHolder();
                switch (type) {
                    case TYPE_ITEM:
                        convertView = mInflater.inflate(R.layout.item1, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.text);
                        break;
                    case TYPE_SEPARATOR:
                        convertView = mInflater.inflate(R.layout.item2, null);
                        holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
                        break;
                }
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.textView.setText(mData.get(position));
            return convertView;
        }
 
    }
 
    public static class ViewHolder {
        public TextView textView;
    }
}

Let’s run what we wrote. Yo will see separators after each 4-th item in the list.

In the log – nothing exceptional – all convertView is null for visible items both types.

02-05 15:19:03.080: INFO/System.out(1035): getView 0 null type = 0
02-05 15:19:03.112: INFO/System.out(1035): getView 1 null type = 0
02-05 15:19:03.130: INFO/System.out(1035): getView 2 null type = 0
02-05 15:19:03.141: INFO/System.out(1035): getView 3 null type = 0
02-05 15:19:03.160: INFO/System.out(1035): getView 4 null type = 1
02-05 15:19:03.170: INFO/System.out(1035): getView 5 null type = 0
02-05 15:19:03.180: INFO/System.out(1035): getView 6 null type = 0
02-05 15:19:03.190: INFO/System.out(1035): getView 7 null type = 0
02-05 15:19:03.210: INFO/System.out(1035): getView 8 null type = 0
02-05 15:19:03.210: INFO/System.out(1035): getView 9 null type = 1

Scroll list and see what happens:

02-05 15:19:54.160: INFO/System.out(1035): getView 10 null type = 0
02-05 15:19:57.440: INFO/System.out(1035): getView 11 [email protected] type = 0
02-05 15:20:01.310: INFO/System.out(1035): getView 12 [email protected] type = 0
02-05 15:20:01.880: INFO/System.out(1035): getView 13 [email protected] type = 0
02-05 15:20:02.869: INFO/System.out(1035): getView 14 null type = 1
02-05 15:20:06.489: INFO/System.out(1035): getView 15 [email protected] type = 0
02-05 15:20:07.749: INFO/System.out(1035): getView 16 [email protected] type = 0
02-05 15:20:10.250: INFO/System.out(1035): getView 17 [email protected] type = 0
02-05 15:20:11.661: INFO/System.out(1035): getView 18 android.widget.LinearLayou[email protected] type = 0
02-05 15:20:13.180: INFO/System.out(1035): getView 19 [email protected] type = 1
02-05 15:20:16.900: INFO/System.out(1035): getView 20 [email protected] type = 0
02-05 15:20:25.690: INFO/System.out(1035): getView 21 [email protected] type = 0

convertView is null for separator view type until first separator is visible. When it goes off the screen – view also comes to the Recycler and convertView comes to play.

BaseAdapter中重写getview的心得以及发现convertView回收的机制,布布扣,bubuko.com

时间: 2024-12-28 16:07:57

BaseAdapter中重写getview的心得以及发现convertView回收的机制的相关文章

Listview之优化BaseAdapter中的getView中的contentView

BaseAdapter中getView中改动的地方: @Override public View getView(int position, View contentView, ViewGroup arg2) { TextView textview; ImageView imageView; //判断contentView是否为空,为空重新创建 if(contentView == null){ contentView =layoutInflater.inflate(R.layout.list_i

关于BaseAdapter的使用及优化心得

对于Android程序员来说,BaseAdapter肯定不会陌生,灵活而优雅是BaseAdapter最大的特点.开发者可以通过构造BaseAdapter并搭载到ListView或者GridView这类多控件布局上面,实现软件所需要的布局效果.同时,BaseAdapter也是适配器里面最基础的一个类,其他的例如SimpleAdapter.ArrayAdapter都是直接或者间接继承BaseAdapter,所以说学好BaseAdapter基本就熟练掌握了适配器的使用了. 本文需要具备一些Androi

在Hadoop中重写FileInputFormat类以处理二进制格式存储的整数

最近开始使用MapReduce,发现网上大部分例子都是对文本数据进行处理的,也就是说在读取输入数据时直接使用默认的TextInputFormat进行处理即可.对于文本数据处理,这个类还是能满足一部分应用场景.但是如果要处理以二进制形式结构化记录存储的文件时,这些类就不再适合了. 本文以一个简单的应用场景为例:对按照二进制格式存储的整数做频数统计.当然,也可以在此基础上实现排序之类的其他应用.实现该应用的主要难点就是如何处理输入数据.参考<权威指南·第三版>得知需要继承FileInputForm

[Android]对BaseAdapter中ViewHolder编写简化(转)

来自博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html 在Android项目中,经常都会用到ListView这个控件,而相应的Adapter中getView()方法的编写有一个标准的形式,如下: 1 @Override 2 public View getView(int position, View convertView, ViewGroup parent) { 3 ViewHolder holder; 4 if(null == c

U3D 2D中给精灵添加刚体后 发现精灵会倒 ..

U3D 2D中给精灵添加刚体后 发现精灵会倒 .. 这是因为 没有禁用z轴上面的刚体力造成..只有把刚体上面的 z轴刚体力 冻结掉就可以了 方法一: 红框中Z 复选框勾起来就可以了 方法二 : void Awake() { GetComponent<Rigidbody2D>().freezeRotation = true; }

关于ArrayAdapter中的getView函数

我曾想利用ArrayAdapter中的getView来获取ListView中每个item的View对象.结果是,无论我怎么对View对象进行更改都不产生影响.不会变是理所当然的,因为getView,其实是"createView".下面是我参考的源代码:  public View getView(int position, View convertView, ViewGroup parent) {         return createViewFromResource(positio

在JavaScript中重写jQuery对象的方法

jQuery是一个很好的类库,它给我们解决了很多的客户端编程,任何东西都不是万能的,当它不能满足我们的需求时我们需要对它进行重写,同时也不要影响其原有的功能或者修改其原有的功能:我现在的web应用程序大多数时候的数据交互都是通过Ajax来完成的,这样就可以将一些隐藏字段的数据保存在HTML标签的属性中,使HTML标签的代码量减少,如:ID,Timestamp等等,这些不需要用户输入但又不得不提交的字段,通过表单提交的做法是 <input name="ID" value="

【转载】 C++多继承中重写不同基类中相同原型的虚函数

本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: virtual void TestA(); }; class CBaseB { public: virtual void TestB(); }; class CDerived : public CBaseA, public CBaseB { public: virtual void TestA()

C#学习笔记(16)——C#中重写(override)和覆盖(new)的区别

说明(2017-7-17 23:04:45): 原文: C#中重写(override)和覆盖(new)的区别 重写 用关键字 virtual 修饰的方法,叫虚方法.可以在子类中用override 声明同名的方法,这叫"重写".相应的没有用virtual修饰的方法,我们叫它实方法.重写会改变父类方法的功能.看下面演示代码: #region 重写 public class C1{    public virtual string GetName()    {        return &