Android:How to customize CursorAdapter(如何自定义CursorAdapter)

本文深入讲解了如何创建自定义CursorAdapter,并重点介绍了其在Android应用中实现数据绑定的方法。通过示例代码,读者可以了解如何扩展SimpleCursorAdapter,以及如何实现Filterable接口以支持列表过滤功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters/


Hey everyone,

Now that we have the SimpleCursorAdapter figured out, when writing your Custom Cursor Adapter you’ll see where some of the parameters come into play. Here’s an example of a Custom Cursor Adapter that I built:

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
public class ContactListCursorAdapter extends SimpleCursorAdapter implements Filterable {
 
     private Context context;
 
     private int layout;
 
     public ContactListCursorAdapter (Context context, int layout, Cursor c, String[] from, int [] to) {
         super (context, layout, c, from, to);
         this .context = context;
         this .layout = layout;
     }
 
     @Override
     public View newView(Context context, Cursor cursor, ViewGroup parent) {
 
         Cursor c = getCursor();
 
         final LayoutInflater inflater = LayoutInflater.from(context);
         View v = inflater.inflate(layout, parent, false );
 
         int nameCol = c.getColumnIndex(People.NAME);
 
         String name = c.getString(nameCol);
 
         /**
          * Next set the name of the entry.
          */    
         TextView name_text = (TextView) v.findViewById(R.id.name_entry);
         if (name_text != null ) {
             name_text.setText(name);
         }
 
         return v;
     }
 
     @Override
     public void bindView(View v, Context context, Cursor c) {
 
         int nameCol = c.getColumnIndex(People.NAME);
 
         String name = c.getString(nameCol);
 
         /**
          * Next set the name of the entry.
          */    
         TextView name_text = (TextView) v.findViewById(R.id.name_entry);
         if (name_text != null ) {
             name_text.setText(name);
         }
     }
 
     @Override
     public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
         if (getFilterQueryProvider() != null ) { return getFilterQueryProvider().runQuery(constraint); }
 
         StringBuilder buffer = null ;
         String[] args = null ;
         if (constraint != null ) {
             buffer = new StringBuilder();
             buffer.append( "UPPER(" );
             buffer.append(People.NAME);
             buffer.append( ") GLOB ?" );
             args = new String[] { constraint.toString().toUpperCase() + "*" };
         }
 
         return context.getContentResolver().query(People.CONTENT_URI, null ,
                 buffer == null ? null : buffer.toString(), args, People.NAME + " ASC" );
     }
}

The Custom Cursor Adapter created above extends the SimpleCursorAdapter and also implements the Filterable class (which I’ll get to later). Here you can see the importance of passing in the layout of the list row entry as in the cursor adapter when the actual views in the list are being built (via newView and bindView) and both methods use this layout to inflate the view, which you can then use to retrieve the TextView / ImageView / etc that are custom designed in your list entry row XML file.

In my example, when a view is created for the first time (via newView), you first inflate the view and retrieve the cursor WHICH YOU PASSED IN. Remember this as depending on which columns you told your cursor to return, those are the columns that you can retrieve information from in your Custom Cursor Adapter. In other words, if my cursor looked like:

1
Cursor c = getContentResolver().query(People.CONTENT_URI, new String[] { People._ID, People.NAME }, null , null , null );

And I tried to retrieve the People.NUMBER column from my cursor, it will return an SQL exception.

The rest should be pretty self explanatory – simply grab the data you want and do what you want with the data (i.e. calculations, grabbing images, etc) and then put them into your inflated views.

One more thing to note is that YOU MUST place something into each view (even if it is NULL). For instance, had my adapter looked like:

1
2
3
4
5
6
String name = c.getString(nameCol);
 
TextView name_text = (TextView) v.findViewById(R.id.name_entry);
if (name_text != null && name != null ) {
       name_text.setText(name);
}

Then you’ll notice some weird behavior – namely, that you’ll see the names start shifting as you scroll up and down the list. What happens is that if you don’t instantiate and place something into your TextView (basically to act as a place holder) then in your bindView method nothing gets bound to some of the TextViews and thus the shifting. So basically, if you see stuff shifting around in your lists, then that’s a big flag for make sure you are binding things to all of your views in both your newView and bindView methods.

Finally, a little on the Filterable implementation. If you want a list that filters as the user starts to type then this is what you need to do. Once you implement the Filterable class, you’ll need to override the runQueryOnBackgroundThread() method and this code snippet:

1
2
3
4
5
6
7
8
9
StringBuilder buffer = null ;
String[] args = null ;
if (constraint != null ) {
      buffer = new StringBuilder();
      buffer.append( "UPPER(" );
      buffer.append(People.NAME);
      buffer.append( ") GLOB ?" );
      args = new String[] { constraint.toString().toUpperCase() + "*" };
}

And basically the StringBuilder is just building the constraint that the cursor will run. If you want to mess with this, then you’ll need to keep:

1
2
3
4
buffer = new StringBuilder();
buffer.append( "UPPER(" );
// THIS YOU CAN CHANGE
buffer.append( ") GLOB ?" );

But you can customize the rest of the constraint, for instance:

1
2
3
4
buffer = new StringBuilder();
buffer.append( "UPPER(" );
buffer.append(People.NAME + " IS NOT NULL" + " AND " + People.NUMBER_KEY + " LIKE '630%'" );
buffer.append( ") GLOB ?" );

And that’s it! Next post will be on BaseAdapters, and I’ll also talk a little on the comparison between these two adapters.

To see all posts on CursorAdapters, please visithttp://thinkandroid.wordpress.com/category/android-tutorials/cursoradapter-tutorials/

Happy coding.

- jwei



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值