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() |