转:CursorAdapter

继承于BaseAdapter,它是个虚类,它为cursor和ListView提供了连接的桥梁。
public abstract class CursorAdapter extends BaseAdapter

 
直接子类只有ResourceCursorAdapter
Class Overview
Adapter that exposes data from a Cursor to a ListView widget.
The Cursor must include a column named "_id" or this class will not work.

注意cursor的必须要有个命名为"_id"的列。比如Contacts._ID就为"_id"
必须实现以下函数

abstract View newView(Context  context, Cursor  cursor, ViewGroup  parent)
//Makes a new view to hold the data pointed to by cursor.
abstract void bindView(View  view, Context  context, Cursor  cursor)
//Bind an existing view to the data pointed to by cursor

 注意
newView该函数第一次回调用后,如果数据增加后也会再调用,但是重绘是不会调用的。
数据增加后,回调用该函数来生成与新增数据相对应的view。
bindView函数第一次回调用后,如果数据更新也会再调用,但重绘会再次调用的。
【总的来说应该是在调用bindView如果发现view为空会先调用newView来生成view】

import java.util.List;
import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;
import android.content.Context;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ListView;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CursorAdapter;
import android.widget.TextView;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
import android.view.View.OnClickListener;     
import android.widget.Button; 
public class HelloCursor extends ListActivity {
    private static String[] PROJECTION = new String[] { Contacts._ID,
            Contacts.DISPLAY_NAME };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Cursor c = getContentResolver().query(Contacts.CONTENT_URI, PROJECTION,
                null, null, Contacts.DISPLAY_NAME + " COLLATE NOCASE");
        startManagingCursor(c);
        MyCursorAdapter adapter = new MyCursorAdapter(this, R.layout.list_row,
                c);
        this.setListAdapter(adapter);
        Button button = (Button)findViewById(R.id.Button01); 
        OnClickListener listener=new OnClickListener(){
            @Override    
            public void onClick(View v) {     
                doAction();     
            }         
        };
        button.setOnClickListener(listener);
        mHandler = new Handler();
       
    }

    private String[] mStrings = { "hubin", "hudashi", "robin" };
    int cnt = 0;
    private Handler mHandler;
    
    class AddContactThread implements Runnable {
        public void run() {
            int nStringLength = mStrings.length;
            int randomNumber = 0;
            ContentValues newValues = new ContentValues();
            String tempString = null;
            randomNumber = (int) (Math.random() % 10);
            for (int i = 0; i < nStringLength; i++) {
                tempString = mStrings + cnt + randomNumber;
                newValues.put(Contacts.DISPLAY_NAME, tempString);
                getContentResolver().insert(RawContacts.CONTENT_URI, newValues);
                newValues.clear();

            }
            cnt++;
        }
    }
    AddContactThread addContact=new AddContactThread();
    void doAction()
    {
         mHandler.post(addContact);
    }
}
class MyCursorAdapter extends CursorAdapter {
    Context  context=null;
    int viewResId;
    public MyCursorAdapter(Context context, int resource, Cursor cursor) {
        super(context,cursor);
        viewResId=resource;
    }
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        
        TextView view =null;
        LayoutInflater vi = null;
        vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view =(TextView)vi.inflate(viewResId, parent, false);
           //v =(TextView)vi.inflate(textViewResourceId,null);
        Log.i("hubin","newView"+view);
        return view;
    }
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        Log.i("hubin","bind"+view);
        TextView nameView = (TextView) view;
        // Set the name
        nameView.setText(cursor
                .getString(cursor.getColumnIndex("DISPLAY_NAME")));
    }
}

 附1:关于newView和bindView一测试结果

newView android.widget.TextView@43b98ea0
bind android.widget.TextView@43b98ea0
newView android.widget.TextView@43b99948
bind android.widget.TextView@43b99948
newView android.widget.TextView@43b9a3f0
bind android.widget.TextView@43b9a3f0
add
bind android.widget.TextView@43b9a3f0
bind android.widget.TextView@43b99948
bind android.widget.TextView@43b98ea0
newView android.widget.TextView@43b9c5b0
bind android.widget.TextView@43b9c5b0
newView android.widget.TextView@43b9d058
bind android.widget.TextView@43b9d058
newView android.widget.TextView@43b9db00
bind android.widget.TextView@43b9db00 

一般书里面也没有介绍如何使用CursorAdapter,要定制自己的CursorAdapter, 要覆盖newView, bindView和changeCursor. 现在以ListView为例来说明:

从上面可以看出,listView不是每次都会调用newView,所以每个item的view对象只会被实例化一次。而每次要绘制item之前,一定会调用bindView。这是动态绑定。如果记录被修改了,在ListView会实时更新。如果要实现数据的延迟加载,可以在bindView中先加载,再启动后台线程加载。

对于那些不用到数据库的应用,也可以用MatrixCursor来生成cursor对象。

看这里:
http://stackoverflow.com/questions/3535074/getview-vs-bindview-in-a-custom-cursoradapter

或者去看android的CustomAdapter的源码.
CustomAdapter覆盖了BaseAdapter的getView方法,并在里面调用了newView()和bindView().所以你就知道这三个方法的调用关系了吧。

adapter的机制和list的机制有关,其实,无论你实际数据项有多少,显示在屏幕上的只有固定个数的item(取决于list的高或宽)。
在list滑动时,判断是否有Item已经滑出屏幕,滑出去的item被释放掉,加入新的item并显示。每次加入新的item就要调用getView()方法了。
打log的话,你会看到,只要你滑动的距离超过一个item项的高度,就会调用一次getView()

看这里:
http://stackoverflow.com/questions/3535074/getview-vs-bindview-in-a-custom-cursoradapter

或者去看android的CustomAdapter的源码.
CustomAdapter覆盖了BaseAdapter的getView方法,并在里面调用了newView()和bindView().所以你就知道这三个方法的调用关系了吧。

adapter的机制和list的机制有关,其实,无论你实际数据项有多少,显示在屏幕上的只有固定个数的item(取决于list的高或宽)。
在list滑动时,判断是否有Item已经滑出屏幕,滑出去的item被释放掉,加入新的item并显示。每次加入新的item就要调用getView()方法了。
打log的话,你会看到,只要你滑动的距离超过一个item项的高度,就会调用一次getView()

猜你喜欢

转载自dukec.iteye.com/blog/2077985