CursorAdapter中getView newView bindView异同

Adapter的作用是界面与数据之间的桥梁,通过设置适配器至ListView控件后(如调用ListView的 setAdapter(ListAdapter adapter)                                                          
),列表的每一项会显示至页面中。其实,当列表里的每一项显示到页面 时,都会调用 Adapter的getView方法 返回一个View,如:                                                                
                               @Override                                                                                                                                                                                                                                                
                               public View getView(int position, View convertView, ViewGroup parent) {                                                                                                                    
                                               return super.getView(position, convertView, parent);                                                                                                                                          
                               }                                                                                                                                                                                                        
CursorAdapter中提供了这两个抽象方法:
//Makes a new view to hold the data pointed to by cursor.
public abstract View newView(Context context, Cursor cursor, ViewGroup parent);
//Bind an existing view to the data pointed to by cursor
public abstract void bindView(View view, Context context, Cursor cursor);

newView和bindView细化了getView中的功能实现,均可写在getView中代 替。

三者的调用顺序为:
getView——>newView——>bindView

转: http://hi.baidu.com/spare_h/blog/item/a826d9d873f7053410df9b52.html

ListView 中getView的原理


ListView的性能优化之convertView和viewHolder

http://www.cnblogs.com/itstudent/p/3729117.html

ListView 和 Adapter 的基础

工作原理:

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

如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!内存肯定溢出。所以我们要复用退出item的视图。是整个listView中new的视图只和显示出来的item个数有关。

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

Android中有个叫做Recycler(反复循环器)的构件,下图是他的工作原理:

CursorAdapter中getView <wbr>newView <wbr>bindView异同

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

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

1.如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中
2. ListView先请求一个type1视图(getView),然后请求其他可见的项目。conVertView在getView中时null的
3. 当item1滚出屏幕,并且一个新的项目从屏幕地段上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1.你只需要设定新的数据返回convertView,不必重新创建一个视图。这样直接使用convertView从而减少了很不不必要view的创建
!!!!!!更快的方式是定义一个ViewHolder,将convertView的tag设置为ViewHolder,不为空是重新使用

ViewHolder只是将需要缓存的那些view封装好,convertView的setTag才是将这些缓存起来供下次调用
当你的listview里布局多样化的时候 viewholder的作用就有比较明显的体现了。 当然了,单一模式的布局一样有性能优化的作用 只是不直观。  假如你2种模式的布局 当发生回收的时候 你会用setTag分别记录是哪两种   这两种模式会被封装到viewholder中进行保存方便你下次使用。 VH就是个静态类 与缓存无关的

这个convertView其实就是最关键的部分  原理上讲 当ListView滑动的过程中 会有item被滑出屏幕 而不再被使用 这时候Android会回收这个条目的view 这个view也就是这里的convertView。

当item1被移除屏幕的时候 我们会重新new一个View给新显示的item_new 而如果使用了这个convertView 我们其实可以复用它 这样就省去了new View的大量开销避免oom问题。

01 publicclassMultipleItemsList extendsListActivity {
02   
03     privateMyCustomAdapter mAdapter;
04   
05     @Override
06     publicvoidonCreate(Bundle savedInstanceState) {
07         super.onCreate(savedInstanceState);
08         mAdapter = newMyCustomAdapter();
09         for(inti = 0; i < 50; i++) {
10             mAdapter.addItem("item "+ i);
11         }
12         setListAdapter(mAdapter);
13     }
14   
15     privateclassMyCustomAdapter extendsBaseAdapter {
16   
17         privateArrayList mData = newArrayList();
18         privateLayoutInflater mInflater;
19   
20         publicMyCustomAdapter() {
21             mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
22         }
23   
24         publicvoidaddItem(finalString item) {
25             mData.add(item);
26             notifyDataSetChanged();
27         }
28   
29         @Override
30         publicintgetCount() {
31             returnmData.size();
32         }
33   
34         @Override
35         publicString getItem(intposition) {
36             returnmData.get(position);
37         }
38   
39         @Override
40         publiclonggetItemId(intposition) {
41             returnposition;
42         }
43   
44         @Override
45         publicView getView(intposition, View convertView, ViewGroup parent) {
46             System.out.println("getView "+ position + " "+ convertView);
47             ViewHolder holder = null;
48             if(convertView == null) {
49                 convertView = mInflater.inflate(R.layout.item1, null);
50                 holder = newViewHolder();
51                 holder.textView = (TextView)convertView.findViewById(R.id.text);
52                 convertView.setTag(holder);
53             } else{
54                 holder = (ViewHolder)convertView.getTag();
55             }
56             holder.textView.setText(mData.get(position));
57             returnconvertView;
58         }
59   
60     }
61   
62     publicstaticclassViewHolder {
63         publicTextView textView;
64     }
65 }

 

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

 



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

 

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

 

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

CursorAdapter中getView <wbr>newView <wbr>bindView异同


 

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

 CursorAdapter中getView <wbr>newView <wbr>bindView异同



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

 

再滚动List

CursorAdapter中getView <wbr>newView <wbr>bindView异同

 

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

 

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

 

再滚动:

02-0514:01:31.069: INFO/System.out(947): getView 11android.widget.LinearLayout@437447d0
02-0514:01:31.142: INFO/System.out(947): getView 12android.widget.LinearLayout@43744ff8
02-0514:01:31.279: INFO/System.out(947): getView 13android.widget.LinearLayout@43743fa8
02-0514:01:31.350: INFO/System.out(947): getView 14android.widget.LinearLayout@43745820
02-0514:01:31.429: INFO/System.out(947): getView 15android.widget.LinearLayout@43746048
02-0514:01:31.550: INFO/System.out(947): getView 16android.widget.LinearLayout@43746870
02-0514:01:31.669: INFO/System.out(947): getView 17android.widget.LinearLayout@43747098
02-0514:01:31.839: INFO/System.out(947): getView 18android.widget.LinearLayout@437478c0
02-0514:03:30.900: INFO/System.out(947): getView 19android.widget.LinearLayout@43748df0
02-0514:03:32.069: INFO/System.out(947): getView 20android.widget.LinearLayout@437430f8

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



ListView优化


http://blog.csdn.net/yucf1988/article/details/6365297

Adapter的作用是界面与数据之间的桥梁,通过设置适配器至ListView控件后(如调用ListView的 setAdapter(ListAdapter adapter)                              
),列表的每一项会显示至页面中。其实,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View,如:                                 
                @Override                                                                                                                         
                public View getView(int position, View convertView, ViewGroup parent) {                                                           
                        return super.getView(position, convertView, parent);                                                                      
                }                                                                                                                                 
我们看一看下面的这段代码:                                                                                                                        
public View getView(int position, View convertView, ViewGroup parent) {                                                                           
View newView = mInflater.inflate(R.layout.list_item, null);                                                                                       
((TextView) newView .findViewById(R.id.text)).setText(DATA[position]);                                                                            
((ImageView) newView .findViewById(R.id.icon)).setImageBitmap(                                                                                    
(position & 1) == 1 ? mIcon1 : mIcon2);                                                                                                           
return newView ;                                                                                                                                  
}                                                                                                                                                 
上面的代码块中,我通过LayoutInflater.inflate(,)将Layout文件--layout.list_item转换为View.                                                          
       (注:Layout也是View的子类,但在android中如果想将xml中的Layout转换为View放入.java代码中操作,只能通过Inflater,而不能通过findViewById())  
这时,如果我的ITEM项有数以千条这样多或更多呢,再以上面代码块的写法,后果自己想想吧。                                                              
                                                                                                                                                  
 于是,改用其它一种写法:                                                                                                                      
public View getView(int position, View convertView, ViewGroup parent) {                                                                           
if (convertView == null) {                                                                                                                        
convertView = mInflater.inflate(R.layout.list_item, null);                                                                                        
}                                                                                                                                                 
((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);                                                                         
((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(                                                                                 
(position & 1) == 1 ? mIcon1 : mIcon2);                                                                                                           
return convertView;                                                                                                                               
}                                                                                                                                                 
这时,上面的代码是不是好了很多?系统将会减少创建很多View。性能得到了很大的提升。                                                                  
到这里,问一下,还有没有优化的方法呢,是有的,请看————》》:                                                                                  
public View getView(int position, View convertView, ViewGroup parent) {                                                                           
ViewHolder holder;                                                                                                                                
if (convertView == null) {                                                                                                                        
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);                                                                              
holder = new ViewHolder();                                                                                                                        
holder.text = (TextView) convertView.findViewById(R.id.text);                                                                                     
holder.icon = (ImageView) convertView.findViewById(R.id.icon);                                                                                    
convertView.setTag(holder);                                                                                                                       
} else {                                                                                                                                          
holder = (ViewHolder) convertView.getTag();                                                                                                       
}                                                                                                                                                 
holder.text.setText(DATA[position]);                                                                                                              
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);                                                                                
return convertView;                                                                                                                               
}       

                                                                                                                                          
 static class ViewHolder {                                                                                                                         
TextView text;                                                                                                                                    
ImageView icon;                                                                                                                                   
}                          




Android 中文 API (102)—— CursorAdapter

 

前言

  本章内容是android.widget.CursorAdapter,版本为Android 2.3 r1,翻译来自"深夜未眠",欢迎访问它的博客:"http://chirs1012f.javaeye.com/",再次感谢"深夜未眠" !期待你一起参与Android API的翻译,联系我over140@gmail.com。 

 

声明

  欢迎转载,但请保留文章原始出处:) 

    博客园:http://www.cnblogs.com/

    Android中文翻译组:http://goo.gl/6vJQl

 

正文

  一、结构

public abstract class CusrorAdapter extends BaseAdpater implements Filterable

 

java.lang.Object

android.widget.BaseAdapter

         android.widget.CursorAdapter

 

直接子类

      ResourceCursorAdapter

间接子类

SimpleCursorAdapter

 

  二、概述

    通过该类可以用Cursor的方式访问数据库,并将查询出来的数据展示到列表视图(ListView)部件上。其中游标携带的结果集中必须有列名为“_id”的列,否则这个类无法工作。

 

  三、构造函数

    public CusorAdapter(Context context,Cursor c)   

           构造函数。每当数据库的数据发生改变时,适配器将调用requery()重新查询以显示最新的数据。

             参数

       context        应用程序上下文。

  c                 用来获取数据的游标(Coursor)

 

    public CusorAdapter(Context context,Cursor c, boolean autoRequery)       

  构造函数。每当数据库的数据发生改变时,适配器将调用requery()重新查询以显示最新的数据。

             参数

       context        应用程序上下文。

  c                 用来获取数据的Coursor

                      autoRequry     设置为true时,每当数据库的数据发生改变时,适配器将调用requery()重新查询以显示最新的数据。

 

  四、公共方法

  public abstract void bindView (View view, Context context, Cursor cursor)

  重用一个已有的view,使其显示当前cursor所指向的数据。

  参数

                   view                已存在的视图返回之前newView方法创建的视图。

                   context          应用程序上下文

                   cursor               用于获取数据的CoursorCoursor已经移到正确的位置。

        

  public void changeCursor (Cursor cursor)

           更改底层的游标为新传入的游标。如果游标已经存在则先关闭这个已存在的游标。

  参数                  

                   cursor               Cursor

 

  public CharSequence convertToString (Cursor cursor)

           cursor转换成CharSequence。子类应该重写这个方法并转换它们的结果。这个方法的默认实现是:当cursor为空时返回一个空串,否则直接返回调用cursortoString()方法。

  参数        

                   cursor               cursor转换成CharSequence对象。

           返回值

             返回表示CharSequence的值。

 

  public int getCount ()

         (译者注:获取适配器中数据的总行数。)

             参见

                      getCount()

 

  public Cursor getCursor ()

           返回当前适配器绑定的Cursor对象。

  返回值

            Cursor对象。

 

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

  获取下拉列表选项指定位置的视图对象

  参数

           position  视图(View)对象的行索引。

           convertView       重用已有的视图(View)对象。备注:在使用前你应该检查一下这个视图对象是否非空并且这个对象的类型是否合适。由此引伸出,如果该对象不能被转换并显示正确的数据,这个方法内部就会重新创建一个合适的视图(View)对象。

           parent  不管是转换后的还是重新创建的视图(View)对象,始终都会依附于parent对象上。

  返回值    

                   返回视图(View)对象,该对象显示数据集指定位置上的数据。

 

  public Filter getFilter ()

  返回一个可以通过一种过滤模式来约束数据的过滤器。

  这个方法通常在Adapter类实现。

  返回值

                   一个用于约束数据的过滤器

 

  public FilterQueryProvider getFilterQueryProvider ()

  返回一个提供过滤的查询过滤器。若过滤器为null,则不再过滤。

  返回值

                   返回当前过滤器对象,如果不存在返回null

                 参见

                   setFilterQueryProvider(android.widget.FilterQueryProvider)

                   runQueryOnBackgroundThread(CharSequence)

 

  public Object getItem (int position)

  (译者注:获取数据集中指定位置上的数据项目)

                  参见

                       getItem(int)

 

  public long getItemId (int position)

         (译者注:获取数据集中的指定位置上的行id。)

             参见

                       getItemId(int)

 

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

  (译者注:获取一个显示数据集中指定位置数据段视图。可以手动创建视图,或者从XML设计文件填充。当视图从XML设计文件填充时,父视图(如GridViewListView等)将接受默认的设计参数,除非使用inflate(int, android.view.ViewGroup, boolean)去指定一个根视图和防止依附于根视图。)

        参见

                   getView(int, View, ViewGroup)

 

  public boolean hasStableIds ()

无论项ID代表的基础数据的是否变化都保持不变。

      返回值

  如果为TRUE,意味着相同的ID始终引用相同的对象。

 

  public View newDropDownView (Context context, Cursor cursor, ViewGroup parent)

  生成一个新的下拉视图来保存cursor指向的数据

           参数

             context  应用程序全局信息接口(应用上下文)

  cursor  获取数据的游标,它已经移动到正确的位置

  parent 与新视图相关联的上级视图

  返回值

  新创建的视图。

 

  public abstract View newView (Context context, Cursor cursor, ViewGroup parent)

  新建一个视图来保存cursor指向的数据

           参数

             context  应用程序全局信息接口(应用上下文)

  cursor  获取数据的游标,它已经移动到正确的位置

  parent 与新视图相关联的上级视图

  返回值

                   新创建的视图。

 

  public Cursor runQueryOnBackgroundThread (CharSequence constraint)

  执行含指定约束的查询。此查询依赖于适配器的过滤器。查询是由FilterQueryProvider提供。如果没有指定FilterQueryProvider,当前cursor不过滤只返回。该方法会通过changeCursor(Cursor)方法返回一个Cursor对象,并且关闭掉先前的Cursor对象。这个方法始终在后台线程执行,而不是在应用程序的主线程(或是UI线程)中运行。规定:当参数constraintnull或为空时,该方法返回原始结果。

        参数

              constraint 该查询必须被过滤的约束。

  返回值

  返回含有新的查询结果的Cursor

  参考

         getFilter()

getFilterQueryProvider()

               setFilterQueryProvider(android.widget.FilterQueryProvider)

 

  public void setFilterQueryProvider (FilterQueryProvider filterQueryProvider)

  设置一个过滤器,用来过滤当前的Cursor对象。当这个适配器需要进行过滤操作时, runQuery(CharSequence)方法被调用

       参数

  filterQueryProvider  过滤器对象,设置为null时,就相当于移除了该过滤器。

                参考

                       getFilterQueryProvider()

runQueryOnBackgroundThread(CharSequence)

 

  五、受保护方法

  protected void init (Context context, Cursor c, boolean autoRequery)

  (译者注:供构造函数使用初始化相关参数)

 

  protected void onContentChanged ()

       cursor 对象上的 ContentObserver 接收到改变的通知时就会调用该方法,其默认实现提供了自动重新查询方式,但可以被子类重写。
 

  六、补充 

       文章精选

                   android CursorAdapter的监听事件

                   实现基于Android的英文电子词典

 

                                                                          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值